1 /**
2  * zapcard.cpp
3  * This file is part of the YATE Project http://YATE.null.ro
4  *
5  * Zaptel PRI/TDM/FXS/FXO cards signalling and data driver
6  *
7  * Yet Another Telephony Engine - a fully featured software PBX and IVR
8  * Copyright (C) 2004-2014 Null Team
9  *
10  * This software is distributed under multiple licenses;
11  * see the COPYING file in the main directory for licensing
12  * information for this specific distribution.
13  *
14  * This use of this software may be subject to additional restrictions.
15  * See the LEGAL file in the main directory for details.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  */
21 
22 #include <yatephone.h>
23 #include <yatesig.h>
24 
25 #ifdef _WINDOWS
26 #error This module is not for Windows
27 #else
28 
29 extern "C" {
30 #ifdef HAVE_ZAP
31 #ifdef NEW_ZAPTEL_LOCATION
32 #define __LINUX__
33 #include <zaptel/zaptel.h>
34 #else
35 #include <linux/zaptel.h>
36 #endif
37 #else
38 #include <dahdi/user.h>
39 #endif
40 };
41 
42 #include <string.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <sys/ioctl.h>
46 #include <fcntl.h>
47 
48 using namespace TelEngine;
49 namespace { // anonymous
50 
51 class ZapWorkerClient;                   // Worker thread client (implements process())
52 class ZapWorkerThread;                   // Worker thread (calls client's process() in a loop)
53 class ZapDevice;                         // Zaptel I/O device. Implements the interface with the Zaptel driver
54 class ZapInterface;                      // D-channel signalling interface
55 class ZapSpan;                           // Signalling span used to create voice circuits
56 class ZapCircuit;                        // A voice circuit
57 class ZapAnalogCircuit;                  // A analog circuit
58 class ZapSource;                         // Data source
59 class ZapConsumer;                       // Data consumer
60 class ZapModule;                         // The module
61 
62 #define ZAP_ERR_OVERRUN 0x01             // Flags used to filter interface errors
63 #define ZAP_ERR_ABORT   0x02
64 
65 #define ZAP_CRC_LEN 2                    // The length of the CRC field in signalling packets
66 
67 #ifdef HAVE_ZAP
68 
69 // alarms
70 #define DAHDI_ALARM_RECOVER	ZT_ALARM_RECOVER
71 #define DAHDI_ALARM_LOOPBACK	ZT_ALARM_LOOPBACK
72 #define DAHDI_ALARM_RED		ZT_ALARM_RED
73 #define DAHDI_ALARM_YELLOW	ZT_ALARM_YELLOW
74 #define DAHDI_ALARM_BLUE	ZT_ALARM_BLUE
75 #define DAHDI_ALARM_NOTOPEN	ZT_ALARM_NOTOPEN
76 
77 
78 // events
79 #define DAHDI_EVENT_NONE		ZT_EVENT_NONE
80 #define DAHDI_EVENT_ONHOOK		ZT_EVENT_ONHOOK
81 #define DAHDI_EVENT_RINGOFFHOOK		ZT_EVENT_RINGOFFHOOK
82 #define DAHDI_EVENT_WINKFLASH		ZT_EVENT_WINKFLASH
83 #define DAHDI_EVENT_ALARM		ZT_EVENT_ALARM
84 #define DAHDI_EVENT_NOALARM		ZT_EVENT_NOALARM
85 #define DAHDI_EVENT_ABORT		ZT_EVENT_ABORT
86 #define DAHDI_EVENT_OVERRUN		ZT_EVENT_OVERRUN
87 #define DAHDI_EVENT_BADFCS		ZT_EVENT_BADFCS
88 #define DAHDI_EVENT_DIALCOMPLETE	ZT_EVENT_DIALCOMPLETE
89 #define DAHDI_EVENT_RINGERON		ZT_EVENT_RINGERON
90 #define DAHDI_EVENT_RINGEROFF		ZT_EVENT_RINGEROFF
91 #define DAHDI_EVENT_HOOKCOMPLETE	ZT_EVENT_HOOKCOMPLETE
92 #define DAHDI_EVENT_BITSCHANGED		ZT_EVENT_BITSCHANGED
93 #define DAHDI_EVENT_PULSE_START		ZT_EVENT_PULSE_START
94 #define DAHDI_EVENT_TIMER_EXPIRED	ZT_EVENT_TIMER_EXPIRED
95 #define DAHDI_EVENT_TIMER_PING		ZT_EVENT_TIMER_PING
96 #define DAHDI_EVENT_RINGBEGIN		ZT_EVENT_RINGBEGIN
97 #define DAHDI_EVENT_POLARITY   		ZT_EVENT_POLARITY
98 
99 #ifdef ZT_EVENT_REMOVED
100 #define DAHDI_EVENT_REMOVED		ZT_EVENT_REMOVED
101 #endif
102 
103 #define DAHDI_EVENT_PULSEDIGIT 		ZT_EVENT_PULSEDIGIT
104 #define DAHDI_EVENT_DTMFDOWN   		ZT_EVENT_DTMFDOWN
105 #define DAHDI_EVENT_DTMFUP  		ZT_EVENT_DTMFUP
106 #define DAHDI_EVENT_PULSEDIGIT		ZT_EVENT_PULSEDIGIT
107 
108 // hook events
109 #define DAHDI_ONHOOK	ZT_ONHOOK
110 #define DAHDI_OFFHOOK	ZT_OFFHOOK
111 #define DAHDI_WINK	ZT_WINK
112 #define DAHDI_FLASH	ZT_FLASH
113 #define DAHDI_START	ZT_START
114 #define DAHDI_RING	ZT_RING
115 #define DAHDI_RINGOFF	ZT_RINGOFF
116 
117 // flush buffers
118 #define DAHDI_FLUSH_READ	ZT_FLUSH_READ
119 #define DAHDI_FLUSH_WRITE	ZT_FLUSH_WRITE
120 #define DAHDI_FLUSH_BOTH	ZT_FLUSH_BOTH
121 #define DAHDI_FLUSH_EVENT	ZT_FLUSH_EVENT
122 #define DAHDI_FLUSH_ALL		ZT_FLUSH_ALL
123 
124 // formats
125 #define DAHDI_LAW_DEFAULT	ZT_LAW_DEFAULT
126 #define DAHDI_LAW_MULAW		ZT_LAW_MULAW
127 #define DAHDI_LAW_ALAW		ZT_LAW_ALAW
128 
129 // dial operations
130 #define DAHDI_DIAL_OP_APPEND	ZT_DIAL_OP_APPEND
131 #define DAHDI_DIAL_OP_REPLACE	ZT_DIAL_OP_REPLACE
132 #define DAHDI_DIAL_OP_CANCEL	ZT_DIAL_OP_CANCEL
133 
134 // signalling types
135 #define DAHDI_SIG_NONE		ZT_SIG_NONE
136 #define DAHDI_SIG_FXSLS		ZT_SIG_FXSLS
137 #define DAHDI_SIG_FXSGS		ZT_SIG_FXSGS
138 #define DAHDI_SIG_FXSKS		ZT_SIG_FXSKS
139 #define DAHDI_SIG_FXOLS		ZT_SIG_FXOLS
140 #define DAHDI_SIG_FXOGS		ZT_SIG_FXOGS
141 #define DAHDI_SIG_FXOKS		ZT_SIG_FXOKS
142 #define DAHDI_SIG_EM		ZT_SIG_EM
143 #define DAHDI_SIG_CLEAR		ZT_SIG_CLEAR
144 #define DAHDI_SIG_HDLCRAW	ZT_SIG_HDLCRAW
145 #define DAHDI_SIG_HDLCFCS	ZT_SIG_HDLCFCS
146 #define DAHDI_SIG_HDLCNET	ZT_SIG_HDLCNET
147 #define DAHDI_SIG_SLAVE		ZT_SIG_SLAVE
148 #define DAHDI_SIG_SF		ZT_SIG_SF
149 #define DAHDI_SIG_CAS		ZT_SIG_CAS
150 #define DAHDI_SIG_DACS		ZT_SIG_DACS
151 #define DAHDI_SIG_EM_E1		ZT_SIG_EM_E1
152 #define DAHDI_SIG_DACS_RBS	ZT_SIG_DACS_RBS
153 #define DAHDI_SIG_HARDHDLC	ZT_SIG_HARDHDLC
154 
155 // tonedetect
156 #define DAHDI_TONEDETECT_ON	ZT_TONEDETECT_ON
157 #define DAHDI_TONEDETECT_MUTE	ZT_TONEDETECT_MUTE
158 
159 // dtmfs
160 #define DAHDI_MAX_DTMF_BUF	ZT_MAX_DTMF_BUF
161 #define DAHDI_TONE_DTMF_0	ZT_TONE_DTMF_0
162 #define DAHDI_TONE_DTMF_1	ZT_TONE_DTMF_1
163 #define DAHDI_TONE_DTMF_2	ZT_TONE_DTMF_2
164 #define DAHDI_TONE_DTMF_3	ZT_TONE_DTMF_3
165 #define DAHDI_TONE_DTMF_4	ZT_TONE_DTMF_4
166 #define DAHDI_TONE_DTMF_5	ZT_TONE_DTMF_5
167 #define DAHDI_TONE_DTMF_6	ZT_TONE_DTMF_6
168 #define DAHDI_TONE_DTMF_7	ZT_TONE_DTMF_7
169 #define DAHDI_TONE_DTMF_8	ZT_TONE_DTMF_8
170 #define DAHDI_TONE_DTMF_9	ZT_TONE_DTMF_9
171 #define DAHDI_TONE_DTMF_s	ZT_TONE_DTMF_s
172 #define DAHDI_TONE_DTMF_p	ZT_TONE_DTMF_p
173 #define DAHDI_TONE_DTMF_A	ZT_TONE_DTMF_A
174 #define DAHDI_TONE_DTMF_B	ZT_TONE_DTMF_B
175 #define DAHDI_TONE_DTMF_C	ZT_TONE_DTMF_C
176 #define DAHDI_TONE_DTMF_D	ZT_TONE_DTMF_D
177 
178 // ioctl operations
179 #define DAHDI_SIG_EM		ZT_SIG_EM
180 #define DAHDI_GETEVENT		ZT_GETEVENT
181 #define DAHDI_SPECIFY		ZT_SPECIFY
182 #define DAHDI_SET_BLOCKSIZE	ZT_SET_BLOCKSIZE
183 #define DAHDI_SET_BUFINFO	ZT_SET_BUFINFO
184 #define DAHDI_SETLAW		ZT_SETLAW
185 #define DAHDI_AUDIOMODE		ZT_AUDIOMODE
186 #define DAHDI_ECHOCANCEL	ZT_ECHOCANCEL
187 #define DAHDI_DIAL		ZT_DIAL
188 #define DAHDI_HOOK		ZT_HOOK
189 #define DAHDI_TONEDETECT	ZT_TONEDETECT
190 #define DAHDI_SETPOLARITY	ZT_SETPOLARITY
191 #define DAHDI_SETLINEAR		ZT_SETLINEAR
192 #define DAHDI_SET_DIALPARAMS	ZT_SET_DIALPARAMS
193 #define DAHDI_GET_PARAMS	ZT_GET_PARAMS
194 #define DAHDI_SPANSTAT		ZT_SPANSTAT
195 #define DAHDI_GET_DIALPARAMS	ZT_GET_DIALPARAMS
196 #define DAHDI_ECHOTRAIN		ZT_ECHOTRAIN
197 #define DAHDI_FLUSH		ZT_FLUSH
198 #define DAHDI_SENDTONE		ZT_SENDTONE
199 #define DAHDI_GETVERSION	ZT_GETVERSION
200 
201 // policies
202 #define DAHDI_POLICY_IMMEDIATE  ZT_POLICY_IMMEDIATE
203 
204 // data types
205 #define dahdi_params		zt_params
206 #define dahdi_bufferinfo	zt_bufferinfo
207 #define dahdi_dialoperation	zt_dialoperation
208 #define dahdi_dialparams	zt_dialparams
209 #define	dahdi_spaninfo		zt_spaninfo
210 #define dahdi_versioninfo 	zt_versioninfo
211 
212 #endif
213 // Worker thread client (implements process())
214 class ZapWorkerClient
215 {
216     friend class ZapWorkerThread;
217 public:
~ZapWorkerClient()218     virtual ~ZapWorkerClient() { stop(); }
219     bool running() const;
220     // Return true to tell the worker to call again
221     // Return false to yield
222     virtual bool process() = 0;
223 protected:
ZapWorkerClient()224     inline ZapWorkerClient() : m_thread(0) {}
225     // Start thread if not started
226     bool start(Thread::Priority prio, DebugEnabler* dbg, const String& addr);
227     // Stop thread if started
228     void stop();
229 private:
230     ZapWorkerThread* m_thread;
231 };
232 
233 // Worker thread (calls client's process() in a loop)
234 class ZapWorkerThread : public Thread
235 {
236 public:
ZapWorkerThread(ZapWorkerClient * client,const String & addr,Priority prio=Normal)237     inline ZapWorkerThread(ZapWorkerClient* client, const String& addr, Priority prio = Normal)
238 	: Thread(s_threadName,prio), m_client(client), m_address(addr)
239 	{}
240     virtual ~ZapWorkerThread();
241     // Call client's process() in a loop
242     virtual void run();
243     static const char* s_threadName;
244 private:
245     ZapWorkerClient* m_client;
246     String m_address;
247 };
248 
249 // I/O device
250 class ZapDevice : public GenObject
251 {
252 public:
253     // Flags to check alarms
254     enum Alarm {
255 	Recover  = DAHDI_ALARM_RECOVER,     // Recovering from alarm
256 	Loopback = DAHDI_ALARM_LOOPBACK,    // In loopback
257 	Red      = DAHDI_ALARM_RED,         // Interface is down
258 	Yellow   = DAHDI_ALARM_YELLOW,      // Remote peer doesn't see us
259 	Blue     = DAHDI_ALARM_BLUE,        // We don't see the remote peer
260 	NotOpen  = DAHDI_ALARM_NOTOPEN
261     };
262 
263     // List of events
264     enum Event {
265 	None 		= DAHDI_EVENT_NONE,
266 	OnHook 		= DAHDI_EVENT_ONHOOK,
267 	OffHookRing 	= DAHDI_EVENT_RINGOFFHOOK,
268 	WinkFlash 	= DAHDI_EVENT_WINKFLASH,
269 	Alarm 		= DAHDI_EVENT_ALARM,
270 	NoAlarm 	= DAHDI_EVENT_NOALARM,
271 	HdlcAbort 	= DAHDI_EVENT_ABORT,
272 	HdlcOverrun 	= DAHDI_EVENT_OVERRUN,
273 	BadFCS		= DAHDI_EVENT_BADFCS,
274 	DialComplete	= DAHDI_EVENT_DIALCOMPLETE,
275 	RingerOn	= DAHDI_EVENT_RINGERON,
276 	RingerOff	= DAHDI_EVENT_RINGEROFF,
277 	HookComplete	= DAHDI_EVENT_HOOKCOMPLETE,
278 	BitsChanged	= DAHDI_EVENT_BITSCHANGED,  // Bits changing on a CAS/User channel
279 	PulseStart	= DAHDI_EVENT_PULSE_START,   // Beginning of a pulse coming on its way
280 	Timeout		= DAHDI_EVENT_TIMER_EXPIRED,
281 	TimerPing	= DAHDI_EVENT_TIMER_PING,
282 	RingBegin	= DAHDI_EVENT_RINGBEGIN,
283 	Polarity	= DAHDI_EVENT_POLARITY,        // Polarity reversal event
284 #ifdef DAHDI_EVENT_REMOVED
285 	Removed		= DAHDI_EVENT_REMOVED,
286 #endif
287 	// These are event masks
288 	PulseDigit	= DAHDI_EVENT_PULSEDIGIT,    // This is OR'd with the digit received
289 	DtmfDown	= DAHDI_EVENT_DTMFDOWN,        // Ditto for DTMF key down event
290 	DtmfUp		= DAHDI_EVENT_DTMFUP,            // Ditto for DTMF key up event
291 	DigitEvent	= DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFDOWN | DAHDI_EVENT_DTMFUP
292     };
293 
294     // List of hook to send events
295     enum HookEvent {
296 	HookOn      = DAHDI_ONHOOK,
297 	HookOff     = DAHDI_OFFHOOK,
298 	HookWink    = DAHDI_WINK,
299 	HookFlash   = DAHDI_FLASH,
300 	HookStart   = DAHDI_START,
301 	HookRing    = DAHDI_RING,
302 	HookRingOff = DAHDI_RINGOFF
303     };
304 
305     // Rx Hook states, not exported from zaptel.h in user mode
306     enum RxSigState {
307 	RxSigOnHook = 0,
308 	RxSigOffHook,
309 	RxSigStart,
310 	RxSigRing,
311 	RxSigInitial
312     };
313 
314     // List of valid IOCTL requests
315     enum IoctlRequest {
316 	SetChannel     = 0,              // Specify a channel number for an opened device
317 	SetBlkSize     = 1,              // Set data I/O block size
318 	SetBuffers     = 2,              // Set buffers
319 	SetFormat      = 3,              // Set format
320 	SetAudioMode   = 4,              // Set audio mode
321 	SetEchoCancel  = 5,              // Set echo cancel
322 	SetDial        = 6,              // Append, replace, or cancel a dial string
323 	SetHook        = 7,              // Set Hookswitch Status
324 #ifdef DAHDI_TONEDETECT
325 	SetToneDetect  = 8,              // Set tone detection
326 #else
327 	SetToneDetect  = 101,
328 #endif
329 	SetPolarity    = 10,             // Set line polarity
330 	SetLinear      = 11,             // Temporarily set the channel to operate in linear mode
331 	SetDialParams  = 12,             // Set dialing parameters
332 	GetParams      = 20,             // Get device (channel) parameters
333 	GetEvent       = 21,             // Get events from device
334 	GetInfo        = 22,             // Get device status
335 	GetVersion     = 23,             // Get version
336 	GetDialParams  = 24,             // Get dialing parameters
337 	StartEchoTrain = 30,             // Start echo training
338 	FlushBuffers   = 31,             // Flush buffer(s) and stop I/O
339 	SendTone       = 32,             // Send tone
340     };
341 
342     enum FlushTarget {
343 	FlushRead  = DAHDI_FLUSH_READ,
344 	FlushWrite = DAHDI_FLUSH_WRITE,
345 	FlushRdWr  = DAHDI_FLUSH_BOTH,
346 	FlushEvent = DAHDI_FLUSH_EVENT,
347 	FlushAll   = DAHDI_FLUSH_ALL,
348     };
349 
350     // Zaptel formats
351     enum Format {
352 	Slin    = -1,
353 	Default = DAHDI_LAW_DEFAULT,
354 	Mulaw   = DAHDI_LAW_MULAW,
355 	Alaw    = DAHDI_LAW_ALAW
356     };
357 
358     // Device type: D-channel, voice/data circuit or control
359     enum Type {
360 	DChan,
361 	E1,
362 	T1,
363 	BRI,
364 	FXO,
365 	FXS,
366 	Control,
367 	TypeUnknown
368     };
369 
370     // Dial operations
371     enum DialOperation {
372 	DialAppend  = DAHDI_DIAL_OP_APPEND,
373 	DialReplace = DAHDI_DIAL_OP_REPLACE,
374 	DialCancel  = DAHDI_DIAL_OP_CANCEL
375     };
376 
377     // Create a device used to query the driver (chan=0) or a zaptel channel
378     // Open it if requested
379     ZapDevice(unsigned int chan, bool disableDbg = true, bool open = true);
380     ZapDevice(Type t, SignallingComponent* dbg, unsigned int chan,
381 	unsigned int circuit);
382     virtual ~ZapDevice();
type() const383     inline Type type() const
384 	{ return m_type; }
zapsig() const385     inline int zapsig() const
386 	{ return m_zapsig; }
owner() const387     inline SignallingComponent* owner() const
388 	{ return m_owner; }
address() const389     inline const String& address() const
390 	{ return m_address; }
valid() const391     inline bool valid() const
392 	{ return m_handle >= 0; }
channel() const393     inline unsigned int channel() const
394 	{ return m_channel; }
span() const395     inline int span() const
396 	{ return m_span; }
spanPos() const397     inline int spanPos() const
398 	{ return m_spanPos; }
399     void channel(unsigned int chan, unsigned int circuit);
alarms() const400     inline int alarms() const
401 	{ return m_alarms; }
alarmsText() const402     inline const String& alarmsText() const
403 	{ return m_alarmsText; }
canRead() const404     inline bool canRead() const
405 	{ return m_canRead; }
event() const406     inline bool event() const
407 	{ return m_event || m_savedEvent; }
zapDevName() const408     inline const char* zapDevName() const
409 	{ return (m_type != Control) ? s_zapDevName : s_zapCtlName; }
410     // Get driver/chan format
zapName() const411     inline const String& zapName() const
412 	{ return m_zapName; }
413     // Open the device. Specify channel to use.
414     // Circuit: Set block size (ignore numbufs)
415     // Interface: Check channel mode. Set buffers
416     bool open(unsigned int numbufs, unsigned int bufsize);
417     // Close device. Reset handle
418     void close();
419     // Set data format. Fails if called for an interface
420     bool setFormat(Format format);
421     // Set/unset tone detection
422     bool setDtmfDetect(bool detect);
423     // Update echo canceller (disable if taps is 0)
424     bool setEchoCancel(bool enable, unsigned int taps);
425     // Start echo canceller training for a given period of time (in miliseconds)
426     bool startEchoTrain(unsigned int period);
427     // Enable polling of off-hook state, call only for passive FXO
initHook()428     inline void initHook()
429 	{ m_rxHookSig = RxSigInitial; }
430     // Poll the hook state and save event since a FXO does not generate events
431     void pollHook();
432     // Send hook events
433     bool sendHook(HookEvent event);
434     // Send DTMFs events using dialing or tone structure
435     // dtmf: true - send DTMF (tone dialing), false - send MF (pulse dialing)
436     // op: The dial operation to use
437     // allDigits: true to send all digits at once
438     // useTone: Used only if 'allDigits' is false and 'dtmf' is true
439     bool sendDtmf(const char* tone, bool dtmf = true, DialOperation op = DialAppend,
440 	bool allDigits = true, bool useTone = false);
441     // Send DTMF event using tone structure
442     bool sendDtmf(char tone);
443     // Get an event. Return 0 if no events. Set digit if the event is a DTMF/PULSE
444     int getEvent(char& digit);
445     // Check alarms from this device. Return true if alarms changed
446     bool checkAlarms();
447     // Reset alarms
448     void resetAlarms();
449     // Set clear channel
setLinear(int val,int level=DebugWarn)450     inline bool setLinear(int val, int level = DebugWarn)
451 	{ return ioctl(SetLinear,&val,level); }
452     // Set line polarity
setPolarity(int val,int level=DebugWarn)453     inline bool setPolarity(int val, int level = DebugWarn)
454 	{ return ioctl(SetPolarity,&val,level); }
455     // Flush read and write buffers
456     bool flushBuffers(FlushTarget target = FlushAll);
457     // Check if received data. Wait usec microseconds before returning
458     bool select(unsigned int usec);
459     // Receive data. Return -1 on error or the number of bytes read
460     // If -1 is returned, the caller should check if m_event is set
461     int recv(void* buffer, int len);
462     // Send data. Return -1 on error or the number of bytes written
463     int send(const void* buffer, int len);
464     // Send data. Return -1 on error or the number of bytes written
write(const void * buffer,int len)465     inline int write(const void* buffer, int len)
466 	{ return ::write(m_handle,buffer,len); }
467     // Get driver version and echo canceller
468     bool getVersion(NamedList& dest);
469     // Get driver version and echo canceller
470     bool getSpanInfo(int span, NamedList& dest, int* spans = 0);
471     // Get channel parameters
472     bool getChanParams(NamedList& dest);
473     // Set/get dial parameters (DTMF/MF length)
474     bool dialParams(bool set, int& toneLen, int& mfLen);
475     // Zaptel device names and headers for status
476     static const char* s_zapCtlName;
477     static const char* s_zapDevName;
478 protected:
canRetry()479     inline bool canRetry()
480 	{ return errno == EAGAIN || errno == EINTR; }
481     // Make IOCTL requests on this device
482     bool ioctl(IoctlRequest request, void* param, int level = DebugWarn);
483 private:
484     Type m_type;                         // Device type
485     int m_zapsig;                        // Zaptel signalling type
486     SignallingComponent* m_owner;        // Signalling component owning this device
487     String m_name;                       // Additional debug name for circuits
488     String m_address;                    // User address (interface or circuit)
489     String m_zapName;                    // Zaptel name (Zaptel/channel)
490     int m_handle;                        // The handler
491     unsigned int m_channel;              // The channel this file is used for
492     int m_span;                          // Span this device's channel belongs to
493     int m_spanPos;                       // Physical channel inside span
494     int m_alarms;                        // Device alarms flag
495     int m_rxHookSig;                     // Keep hook status for bridged lines
496     int m_savedEvent;                    // Event saved asynchronously for later
497     String m_alarmsText;                 // Alarms text
498     bool m_canRead;                      // True if there is data to read
499     bool m_event;                        // True if an event occurred when recv/select
500     bool m_readError;                    // Flag used to print read errors
501     bool m_writeError;                   // Flag used to print write errors
502     bool m_selectError;                  // Flag used to print select errors
503     fd_set m_rdfds;
504     fd_set m_errfds;
505     struct timeval m_tv;
506 };
507 
508 // D-channel signalling interface
509 class ZapInterface : public SignallingInterface, public ZapWorkerClient
510 {
511 public:
512     ZapInterface(const NamedList& params);
513     virtual ~ZapInterface();
valid() const514     inline bool valid() const
515 	{ return m_device.valid() && running(); }
516     // Initialize interface. Return false on failure
517     bool init(ZapDevice::Type type, unsigned int code, unsigned int channel,
518 	const NamedList& config, const NamedList& defaults, const NamedList& params);
519     // Remove links. Dispose memory
destruct()520     virtual void destruct()
521 	{ cleanup(true); }
522     // Get this object or an object from the base class
523     virtual void* getObject(const String& name) const;
524     // Send signalling packet
525     virtual bool transmitPacket(const DataBlock& packet, bool repeat, PacketType type);
526     // Interface control. Open device and start worker when enabled, cleanup when disabled
527     virtual bool control(Operation oper, NamedList* params = 0);
528     // Process incoming data
529     virtual bool process();
530     // Called by the factory to create Zaptel interfaces or spans
531     static SignallingComponent* create(const String& type, NamedList& name);
532 protected:
533     // Check if received any data in the last interval. Notify receiver
534     virtual void timerTick(const Time& when);
535     // Check for device events. Notify receiver
536     void checkEvents();
537 private:
cleanup(bool release)538     inline void cleanup(bool release) {
539 	    control(Disable,0);
540 	    attach(0);
541 	    if (release)
542 		RefObject::destruct();
543 	}
544 
545     ZapDevice m_device;                  // The device
546     Thread::Priority m_priority;         // Worker thread priority
547     unsigned char m_errorMask;           // Error mask to filter received error events
548     unsigned int m_numbufs;              // The number of buffers used by the channel
549     unsigned int m_bufsize;              // The buffer size
550     unsigned char* m_buffer;             // Read buffer
551     bool m_readOnly;                     // Read only interface
552     bool m_sendReadOnly;                 // Print send attempt on readonly interface error
553     int m_notify;                        // Notify receiver on channel non idle (0: success. 1: not notified. 2: notified)
554     SignallingTimer m_timerRxUnder;      // RX underrun notification
555     bool m_down;			 // Interface status
556 };
557 
558 // Signalling span used to create voice circuits
559 class ZapSpan : public SignallingCircuitSpan
560 {
561 public:
ZapSpan(const NamedList & params)562     inline ZapSpan(const NamedList& params)
563 	: SignallingCircuitSpan(params.getValue("debugname"),
564 	    static_cast<SignallingCircuitGroup*>(params.getObject("SignallingCircuitGroup")))
565 	{}
~ZapSpan()566     virtual ~ZapSpan()
567 	{}
568     // Create circuits. Insert them into the group
569     bool init(ZapDevice::Type type, unsigned int offset,
570 	const NamedList& config, const NamedList& defaults, const NamedList& params);
571 };
572 
573 // A voice circuit
574 class ZapCircuit : public SignallingCircuit, public ZapWorkerClient
575 {
576 public:
577     ZapCircuit(ZapDevice::Type type, unsigned int code, unsigned int channel,
578 	ZapSpan* span, const NamedList& config, const NamedList& defaults,
579 	const NamedList& params);
~ZapCircuit()580     virtual ~ZapCircuit()
581 	{ cleanup(false); }
destroyed()582     virtual void destroyed()
583 	{ cleanup(true); }
584     // Change circuit status. Clear events on status change
585     // New status is Connect: Open device. Create source/consumer. Start worker
586     // Cleanup on disconnect
587     virtual bool status(Status newStat, bool sync = false);
588     // Update data format for zaptel device and source/consumer
589     virtual bool updateFormat(const char* format, int direction);
590     // Setup echo canceller or start echo canceller training
591     virtual bool setParam(const String& param, const String& value);
592     // Get circuit data
593     virtual bool getParam(const String& param, String& value) const;
594     // Get this circuit or source/consumer
595     virtual void* getObject(const String& name) const;
596     // Process incoming data
597     virtual bool process();
598     // Send an event
599     virtual bool sendEvent(SignallingCircuitEvent::Type type, NamedList* params = 0);
600     // Consume data sent by the consumer
601     void consume(const DataBlock& data);
602 protected:
603     // Close device. Stop worker. Remove source consumer. Change status. Release memory if requested
604     // Reset echo canceller and tone detector if the device is not closed
605     void cleanup(bool release, Status stat = Missing, bool stop = true);
606     // Update format, echo canceller, dtmf detection
607     bool setFormat(ZapDevice::Format format);
608     // Get and process some events
609     void checkEvents();
610     // Process additional events. Return false if not processed
processEvent(int event,char c=0)611     virtual bool processEvent(int event, char c = 0)
612 	{ return false; }
613     // Create source buffer and data source and consumer
614     void createData();
615     // Enqueue received events
616     bool enqueueEvent(SignallingCircuitEvent* event);
617     bool enqueueEvent(int event, SignallingCircuitEvent::Type type);
618     // Enqueue received digits
619     bool enqueueDigit(bool tone, char digit);
620 
621     ZapDevice m_device;                  // The device
622     ZapDevice::Type m_type;              // Circuit type
623     ZapDevice::Format m_format;          // The data format
624     String m_specialMode;                // Special test mode
625     bool m_echoCancel;                   // Echo canceller state
626     bool m_crtEchoCancel;                // Current echo canceller state
627     unsigned int m_echoTaps;             // Echo cancel taps
628     unsigned int m_echoTrain;            // Echo canceller's train period in miliseconds
629     bool m_dtmfDetect;                   // Dtmf detection flag
630     bool m_crtDtmfDetect;                // Current dtmf detection state
631     bool m_canSend;                      // Not a read only circuit
632     unsigned char m_idleValue;           // Value used to fill incomplete source buffer
633     Thread::Priority m_priority;         // Worker thread priority
634     ZapSource* m_source;                 // The data source
635     ZapConsumer* m_consumer;             // The data consumer
636     DataBlock m_sourceBuffer;            // Data source buffer
637     DataBlock m_consBuffer;              // Data consumer buffer
638     unsigned int m_buflen;               // Data block length
639     unsigned int m_consBufMax;           // Max consumer buffer length
640     unsigned int m_consErrors;           // Consumer. Total number of send failures
641     unsigned int m_consErrorBytes;       // Consumer. Total number of lost bytes
642     unsigned int m_consTotal;            // Consumer. Total number of bytes transferred
643     int m_errno;                         // Last write error
644 };
645 
646 // An analog circuit
647 class ZapAnalogCircuit : public ZapCircuit
648 {
649 public:
ZapAnalogCircuit(ZapDevice::Type type,unsigned int code,unsigned int channel,ZapSpan * span,const NamedList & config,const NamedList & defaults,const NamedList & params)650     inline ZapAnalogCircuit(ZapDevice::Type type, unsigned int code, unsigned int channel,
651 	ZapSpan* span, const NamedList& config, const NamedList& defaults,
652 	const NamedList& params)
653 	: ZapCircuit(type,code,channel,span,config,defaults,params),
654 	m_hook(true)
655 	{}
~ZapAnalogCircuit()656     virtual ~ZapAnalogCircuit()
657 	{}
658     // Change circuit status. Clear events on status change
659     // Reserved: Open device and start worker if old status is not Connected
660     // Connect: Create source/consumer
661     // Cleanup on disconnect
662     virtual bool status(Status newStat, bool sync);
663     // Get circuit data
664     virtual bool getParam(const String& param, String& value) const;
665     // Set line polarity
666     virtual bool setParam(const String& param, const String& value);
667     // Send an event
668     virtual bool sendEvent(SignallingCircuitEvent::Type type, NamedList* params = 0);
669     // Process incoming data
670     virtual bool process();
671 protected:
672     // Process additional events. Return false if not processed
673     virtual bool processEvent(int event, char c = 0);
674     // Change hook state if different
675     void changeHook(bool hook);
676 
677     bool m_hook;                         // The remote end's hook status
678 };
679 
680 // Data source
681 class ZapSource : public DataSource
682 {
683 public:
684     ZapSource(ZapCircuit* circuit, const char* format);
685     virtual ~ZapSource();
changeFormat(const char * format)686     inline void changeFormat(const char* format)
687 	{ m_format = format; }
688 private:
689     String m_address;
690 };
691 
692 // Data consumer
693 class ZapConsumer : public DataConsumer
694 {
695     friend class ZapCircuit;
696 public:
697     ZapConsumer(ZapCircuit* circuit, const char* format);
698     virtual ~ZapConsumer();
changeFormat(const char * format)699     inline void changeFormat(const char* format)
700 	{ m_format = format; }
Consume(const DataBlock & data,unsigned long tStamp,unsigned long flags)701     virtual unsigned long Consume(const DataBlock& data, unsigned long tStamp, unsigned long flags)
702 	{ if (m_circuit) m_circuit->consume(data); return invalidStamp(); }
703 private:
704     ZapCircuit* m_circuit;
705     String m_address;
706 };
707 
708 // The Zaptel module
709 class ZapModule : public Module
710 {
711 public:
712     // Additional module commands
713     enum StatusCommands {
714 	ZapSpans       = 0,              // Show all zaptel spans
715 	ZapChannels    = 1,              // Show all configured zaptel channels
716 	ZapChannelsAll = 2,              // Show all zaptel channels
717 	StatusCmdCount = 3
718     };
719     ZapModule();
720     ~ZapModule();
prefix()721     inline const String& prefix()
722 	{ return m_prefix; }
723     void append(ZapDevice* dev);
724     void remove(ZapDevice* dev);
openClose(bool open)725     inline void openClose(bool open) {
726 	    Lock lock(this);
727 	    if (open)
728 		m_active++;
729 	    else
730 		m_active--;
731 	}
732     virtual void initialize();
733     // Find a device by its Zaptel channel
734     ZapDevice* findZaptelChan(int chan);
735     // Additional module status commands
736     static String s_statusCmd[StatusCmdCount];
737 protected:
738     virtual bool received(Message& msg, int id);
739     virtual void statusModule(String& str);
740     virtual void statusParams(String& str);
741     virtual void statusDetail(String& str);
742     virtual bool commandComplete(Message& msg, const String& partLine,
743 	const String& partWord);
744 private:
745     bool m_init;                         // Already initialized flag
746     String m_prefix;                     // Module prefix
747     String m_statusCmd;                  // Status command for this module (status Zaptel)
748     ObjList m_devices;                   // Device list
749     // Statistics
750     unsigned int m_count;                // The number of devices in the list
751     unsigned int m_active;               // The number of active(opened) devices
752 };
753 
754 
755 /**
756  * Module data and functions
757  */
758 static ZapModule plugin;
759 YSIGFACTORY2(ZapInterface);                      // Factory used to create zaptel interfaces and spans
760 static Mutex s_ifaceNotifyMutex(true,"ZapCard::notify"); // ZapInterface: lock recv data notification counter
761 static Mutex s_sourceAccessMutex(false,"ZapCard::source"); // ZapSource access to pointers
762 static const char* s_chanParamsHdr = "format=Type|ZaptelType|Span|SpanPos|Alarms|UsedBy";
763 static const char* s_spanParamsHdr = "format=Channels|Total|Alarms|Name|Description";
764 
765 // Get a boolean value from received parameters or other sections in config
766 // Priority: parameters, config, defaults
getBoolValue(const char * param,const NamedList & config,const NamedList & defaults,const NamedList & params,bool defVal=false)767 static inline bool getBoolValue(const char* param, const NamedList& config,
768 	const NamedList& defaults, const NamedList& params, bool defVal = false)
769 {
770     defVal = config.getBoolValue(param,defaults.getBoolValue(param,defVal));
771     return params.getBoolValue(param,defVal);
772 }
773 
sendModuleUpdate(const String & notif,const String & device,bool & notifStat,int status=0)774 static void sendModuleUpdate(const String& notif, const String& device, bool& notifStat, int status = 0)
775 {
776     Message* msg = new Message("module.update");
777     msg->addParam("module",plugin.name());
778     msg->addParam("interface",device);
779     msg->addParam("notify",notif);
780     if(notifStat && status == SignallingInterface::LinkUp) {
781 	notifStat = false;
782 	Engine::enqueue(msg);
783 	return;
784     }
785     if (!notifStat && status == SignallingInterface::LinkDown) {
786 	notifStat = true;
787 	Engine::enqueue(msg);
788 	return;
789     }
790     if (notif == "alarm") {
791 	if (status == ZapDevice::Yellow)
792 	    msg->addParam("notify","RAI");
793 	if (status == ZapDevice::Blue)
794 	    msg->addParam("notify","AIS");
795 	Engine::enqueue(msg);
796 	return;
797     }
798     TelEngine::destruct(msg);
799 }
800 
801 /**
802  * ZapWorkerClient
803  */
running() const804 bool ZapWorkerClient::running() const
805 {
806     return m_thread && m_thread->running();
807 }
808 
start(Thread::Priority prio,DebugEnabler * dbg,const String & addr)809 bool ZapWorkerClient::start(Thread::Priority prio, DebugEnabler* dbg, const String& addr)
810 {
811     if (!m_thread)
812 	m_thread = new ZapWorkerThread(this,addr,prio);
813     if (m_thread->running())
814 	return true;
815     if (m_thread->startup())
816 	return true;
817     m_thread->cancel(true);
818     m_thread = 0;
819     Debug(dbg,DebugWarn,"Failed to start %s for %s [%p]",
820 	ZapWorkerThread::s_threadName,addr.c_str(),dbg);
821     return false;
822 }
823 
stop()824 void ZapWorkerClient::stop()
825 {
826     if (!m_thread)
827 	return;
828     m_thread->cancel();
829     while (m_thread)
830 	Thread::yield();
831 }
832 
833 /**
834  * ZapWorkerThread
835  */
836 const char* ZapWorkerThread::s_threadName = "Zap Worker";
837 
~ZapWorkerThread()838 ZapWorkerThread::~ZapWorkerThread()
839 {
840     DDebug(&plugin,DebugAll,"%s is terminated for client (%p): %s",
841 	s_threadName,m_client,m_address.c_str());
842     if (m_client)
843 	m_client->m_thread = 0;
844 }
845 
run()846 void ZapWorkerThread::run()
847 {
848     if (!m_client)
849 	return;
850     DDebug(&plugin,DebugAll,"%s is running for client (%p): %s",
851 	s_threadName,m_client,m_address.c_str());
852     while (true) {
853 	if (m_client->process())
854 	    Thread::check(true);
855 	else
856 	    Thread::yield(true);
857     }
858 }
859 
860 
861 /**
862  * ZapDevice
863  */
864 static TokenDict s_alarms[] = {
865     {"recover",  ZapDevice::Recover},
866     {"loopback", ZapDevice::Loopback},
867     {"yellow",   ZapDevice::Yellow},
868     {"red",      ZapDevice::Red},
869     {"blue",     ZapDevice::Blue},
870     {"not-open", ZapDevice::NotOpen},
871     {0,0}
872 };
873 
874 // Zaptel signalling type
875 static TokenDict s_zaptelSig[] = {
876     {"NONE",     DAHDI_SIG_NONE},           // Channel not configured
877     {"FXSLS",    DAHDI_SIG_FXSLS},
878     {"FXSGS",    DAHDI_SIG_FXSGS},
879     {"FXSKS",    DAHDI_SIG_FXSKS},
880     {"FXOLS",    DAHDI_SIG_FXOLS},
881     {"FXOGS",    DAHDI_SIG_FXOGS},
882     {"FXOKS",    DAHDI_SIG_FXOKS},
883     {"E&M",      DAHDI_SIG_EM},             // Ear & mouth
884     {"CLEAR",    DAHDI_SIG_CLEAR},          // Clear channel
885     {"HDLCRAW",  DAHDI_SIG_HDLCRAW},        // Raw unchecked HDLC
886     {"HDLCFCS",  DAHDI_SIG_HDLCFCS},        // HDLC with FCS calculation
887     {"HDLCNET",  DAHDI_SIG_HDLCNET},        // HDLC Network
888     {"SLAVE",    DAHDI_SIG_SLAVE},          // Slave to another channel
889     {"SF",       DAHDI_SIG_SF},             // Single Freq. tone only, no sig bits
890     {"CAS",      DAHDI_SIG_CAS},           // Just get bits
891     {"DACS",     DAHDI_SIG_DACS},           // Cross connect
892     {"EM_E1",    DAHDI_SIG_EM_E1},          // E1 E&M Variation
893     {"DACS_RBS", DAHDI_SIG_DACS_RBS},       // Cross connect w/ RBS
894     {"HARDHDLC", DAHDI_SIG_HARDHDLC},
895     {0,0}
896 };
897 
898 #define MAKE_NAME(x) { #x, ZapDevice::x }
899 static TokenDict s_events[] = {
900     MAKE_NAME(None),
901     MAKE_NAME(OnHook),
902     MAKE_NAME(OffHookRing),
903     MAKE_NAME(WinkFlash),
904     MAKE_NAME(Alarm),
905     MAKE_NAME(NoAlarm),
906     MAKE_NAME(HdlcAbort),
907     MAKE_NAME(HdlcOverrun),
908     MAKE_NAME(BadFCS),
909     MAKE_NAME(DialComplete),
910     MAKE_NAME(RingerOn),
911     MAKE_NAME(RingerOff),
912     MAKE_NAME(HookComplete),
913     MAKE_NAME(BitsChanged),
914     MAKE_NAME(PulseStart),
915     MAKE_NAME(Timeout),
916     MAKE_NAME(TimerPing),
917     MAKE_NAME(RingBegin),
918     MAKE_NAME(Polarity),
919     MAKE_NAME(PulseDigit),
920     MAKE_NAME(DtmfDown),
921     MAKE_NAME(DtmfUp),
922     MAKE_NAME(DigitEvent),
923 #ifdef DAHDI_EVENT_REMOVED
924     MAKE_NAME(Removed),
925 #endif
926     {0,0}
927 };
928 
929 static TokenDict s_hookEvents[] = {
930     MAKE_NAME(HookOn),
931     MAKE_NAME(HookOff),
932     MAKE_NAME(HookWink),
933     MAKE_NAME(HookFlash),
934     MAKE_NAME(HookStart),
935     MAKE_NAME(HookRing),
936     MAKE_NAME(HookRingOff),
937     {0,0}
938 };
939 
940 static TokenDict s_ioctl_request[] = {
941     MAKE_NAME(SetChannel),
942     MAKE_NAME(SetBlkSize),
943     MAKE_NAME(SetBuffers),
944     MAKE_NAME(SetFormat),
945     MAKE_NAME(SetAudioMode),
946     MAKE_NAME(SetEchoCancel),
947     MAKE_NAME(SetDial),
948     MAKE_NAME(SetHook),
949     MAKE_NAME(SetToneDetect),
950     MAKE_NAME(SetPolarity),
951     MAKE_NAME(SetLinear),
952     MAKE_NAME(SetDialParams),
953     MAKE_NAME(GetParams),
954     MAKE_NAME(GetEvent),
955     MAKE_NAME(GetInfo),
956     MAKE_NAME(GetVersion),
957     MAKE_NAME(GetDialParams),
958     MAKE_NAME(StartEchoTrain),
959     MAKE_NAME(FlushBuffers),
960     MAKE_NAME(SendTone),
961     {0,0}
962 };
963 
964 static TokenDict s_types[] = {
965     MAKE_NAME(DChan),
966     MAKE_NAME(E1),
967     MAKE_NAME(T1),
968     MAKE_NAME(BRI),
969     MAKE_NAME(FXO),
970     MAKE_NAME(FXS),
971     MAKE_NAME(Control),
972     {"not-used", ZapDevice::TypeUnknown},
973     {0,0}
974 };
975 #undef MAKE_NAME
976 
977 static TokenDict s_formats[] = {
978     {"slin",    ZapDevice::Slin},
979     {"default", ZapDevice::Default},
980     {"mulaw",   ZapDevice::Mulaw},
981     {"alaw",    ZapDevice::Alaw},
982     {0,0}
983     };
984 #ifdef HAVE_ZAP
985 const char* ZapDevice::s_zapCtlName = "/dev/zap/ctl";
986 const char* ZapDevice::s_zapDevName = "/dev/zap/channel";
987 #else
988 const char* ZapDevice::s_zapCtlName = "/dev/dahdi/ctl";
989 const char* ZapDevice::s_zapDevName = "/dev/dahdi/channel";
990 #endif
ZapDevice(Type t,SignallingComponent * dbg,unsigned int chan,unsigned int circuit)991 ZapDevice::ZapDevice(Type t, SignallingComponent* dbg, unsigned int chan,
992 	unsigned int circuit)
993     : m_type(t),
994     m_zapsig(-1),
995     m_owner(dbg),
996     m_handle(-1),
997     m_channel(chan),
998     m_span(-1),
999     m_spanPos(-1),
1000     m_alarms(NotOpen),
1001     m_rxHookSig(-1),
1002     m_savedEvent(0),
1003     m_canRead(false),
1004     m_event(false),
1005     m_readError(false),
1006     m_writeError(false),
1007     m_selectError(false)
1008 {
1009     XDebug(&plugin,DebugNote,"ZapDevice type=%s chan=%u owner=%s cic=%u [%p]",
1010 	lookup(t,s_types),chan,dbg?dbg->debugName():"",circuit,this);
1011     close();
1012     this->channel(chan,circuit);
1013     if (m_type == Control || m_type == TypeUnknown) {
1014 	m_owner = 0;
1015 	return;
1016     }
1017     plugin.append(this);
1018 }
1019 
1020 // Create a device used to query the driver (chan=0) or a zaptel channel
ZapDevice(unsigned int chan,bool disableDbg,bool open)1021 ZapDevice::ZapDevice(unsigned int chan, bool disableDbg, bool open)
1022     : m_type(chan ? TypeUnknown : Control),
1023     m_zapsig(-1),
1024     m_owner(0),
1025     m_handle(-1),
1026     m_channel(chan),
1027     m_span(-1),
1028     m_spanPos(-1),
1029     m_alarms(NotOpen),
1030     m_rxHookSig(-1),
1031     m_savedEvent(0),
1032     m_canRead(false),
1033     m_event(false),
1034     m_readError(false),
1035     m_writeError(false),
1036     m_selectError(false)
1037 {
1038     XDebug(&plugin,DebugNote,"ZapDevice(ZaptelQuery) type=%s chan=%u [%p]",
1039 	lookup(m_type,s_types),chan,this);
1040     close();
1041     channel(chan,0);
1042     m_owner = new SignallingCircuitGroup(0,0,"ZaptelQuery");
1043     if (disableDbg)
1044 	m_owner->debugEnabled(false);
1045     if (open)
1046 	this->open(0,160);
1047 }
1048 
~ZapDevice()1049 ZapDevice::~ZapDevice()
1050 {
1051     XDebug(&plugin,DebugNote,"ZapDevice destruct type=%s chan=%u owner=%s [%p]",
1052 	lookup(m_type,s_types),m_channel,m_owner?m_owner->debugName():"",this);
1053     if (m_type == Control || m_type == TypeUnknown)
1054 	TelEngine::destruct(m_owner);
1055     plugin.remove(this);
1056     close();
1057 }
1058 
channel(unsigned int chan,unsigned int circuit)1059 void ZapDevice::channel(unsigned int chan, unsigned int circuit)
1060 {
1061     m_channel = chan;
1062     m_zapName << plugin.name() << "/" << m_channel;
1063     m_address << (m_owner ? m_owner->debugName() : "");
1064     if (m_type != DChan && m_type != Control && m_address) {
1065 	m_name << "ZapCircuit(" << circuit << "). ";
1066 	m_address << "/" << circuit;
1067     }
1068 }
1069 
1070 // Open the device. Specify channel to use.
1071 // Circuit: Set block size
1072 // Interface: Check channel mode. Set buffers
open(unsigned int numbufs,unsigned int bufsize)1073 bool ZapDevice::open(unsigned int numbufs, unsigned int bufsize)
1074 {
1075     close();
1076 
1077     if (m_type == DChan || m_type == Control)
1078 	m_handle = ::open(zapDevName(),O_RDWR,0600);
1079     else
1080 	m_handle = ::open(zapDevName(),O_RDWR|O_NONBLOCK);
1081     if (m_handle < 0) {
1082 	Debug(m_owner,DebugWarn,"%sFailed to open '%s'. %d: %s [%p]",
1083 	    m_name.safe(),zapDevName(),errno,::strerror(errno),m_owner);
1084 	return false;
1085     }
1086 
1087     // Done if opening the main zaptel device
1088     if (m_type == Control)
1089 	return true;
1090 
1091     // Notify plugin if opened for normal (not for query properties) use
1092     if (m_type != TypeUnknown)
1093 	plugin.openClose(true);
1094 
1095     m_alarms = 0;
1096     m_alarmsText = "";
1097     while (true) {
1098 	// Specify the channel to use
1099 	if (!ioctl(SetChannel,&m_channel))
1100 	    break;
1101 
1102 	struct dahdi_params par;
1103 	if (!ioctl(GetParams,&par))
1104 	    break;
1105 
1106 	m_span = par.spanno;
1107 	m_spanPos = par.chanpos;
1108 	m_zapsig = par.sigtype;
1109 
1110 	checkAlarms();
1111 
1112 	if (m_type != DChan) {
1113 	    if (bufsize && !ioctl(SetBlkSize,&bufsize))
1114 		break;
1115 	    DDebug(m_owner,DebugAll,"%sBlock size set to %u on channel %u [%p]",
1116 		m_name.safe(),bufsize,m_channel,m_owner);
1117 	    return true;
1118 	}
1119 
1120 	// Open for an interface
1121 	// Check channel mode
1122 	if (par.sigtype != DAHDI_SIG_HDLCFCS && par.sigtype != DAHDI_SIG_HARDHDLC) {
1123 	    Debug(m_owner,DebugWarn,"Channel %u is not in '%s' or '%s' mode [%p]",
1124 		m_channel,lookup(DAHDI_SIG_HDLCFCS,s_zaptelSig),
1125 		lookup(DAHDI_SIG_HARDHDLC,s_zaptelSig),m_owner);
1126 	    break;
1127 	}
1128 	// Set buffers
1129 	struct dahdi_bufferinfo bi;
1130 	bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
1131 	bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
1132 	bi.numbufs = numbufs;
1133 	bi.bufsize = bufsize;
1134 	if (ioctl(SetBuffers,&bi))
1135 	    DDebug(m_owner,DebugAll,"%snumbufs=%u bufsize=%u on channel %u [%p]",
1136 		m_name.safe(),numbufs,bufsize,m_channel,m_owner);
1137 	return true;
1138     }
1139     close();
1140     return false;
1141 }
1142 
1143 // Close device. Reset handle
close()1144 void ZapDevice::close()
1145 {
1146     m_alarms = NotOpen;
1147     m_alarmsText = lookup(NotOpen,s_alarms);
1148     m_span = -1;
1149     m_spanPos = -1;
1150     m_zapsig = -1;
1151     if (!valid())
1152 	return;
1153     ::close(m_handle);
1154     m_handle = -1;
1155     if (m_type != Control && m_type != TypeUnknown)
1156 	plugin.openClose(false);
1157 }
1158 
1159 // Set data format. Fails if called for an interface
setFormat(Format format)1160 bool ZapDevice::setFormat(Format format)
1161 {
1162     if (m_type == DChan)
1163 	return false;
1164     if (!ioctl(SetFormat,&format,0)) {
1165 	Debug(m_owner,DebugNote,"%sFailed to set format '%s' on channel %u [%p]",
1166 	    m_name.safe(),lookup(format,s_formats,String((int)format)),
1167 	    m_channel,m_owner);
1168 	return false;
1169     }
1170     DDebug(m_owner,DebugAll,"%sFormat set to '%s' on channel %u [%p]",
1171 	m_name.safe(),lookup(format,s_formats),m_channel,m_owner);
1172     return true;
1173 }
1174 
1175 // Set/unset tone detection
setDtmfDetect(bool detect)1176 bool ZapDevice::setDtmfDetect(bool detect)
1177 {
1178     int tmp = 0;
1179 #ifdef DAHDI_TONEDETECT
1180     setLinear(0,DebugAll);
1181     if (detect)
1182 	tmp = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
1183 #endif
1184     if (!ioctl(SetToneDetect,&tmp,detect?DebugNote:DebugAll))
1185 	return false;
1186     DDebug(m_owner,DebugAll,"%sTone detector %s on channel %u [%p]",
1187 	m_name.safe(),detect?"started":"stopped",m_channel,m_owner);
1188     return true;
1189 }
1190 
1191 // Update echo canceller (0: disable)
setEchoCancel(bool enable,unsigned int taps)1192 bool ZapDevice::setEchoCancel(bool enable, unsigned int taps)
1193 {
1194     enable = enable && taps;
1195     int tmp = 1;
1196     if (enable && (type() == E1 || type() == T1) &&
1197 	!ioctl(SetAudioMode,&tmp,DebugMild))
1198 	return false;
1199     if (!enable)
1200 	taps = 0;
1201     if (!ioctl(SetEchoCancel,&taps,DebugMild))
1202 	return false;
1203     if (taps)
1204 	DDebug(m_owner,DebugAll,
1205 	    "%sEcho canceller enabled on channel %u (taps=%u) [%p]",
1206 	    m_name.safe(),m_channel,taps,m_owner);
1207     else
1208 	DDebug(m_owner,DebugAll,"%sEcho canceller disabled on channel %u [%p]",
1209 	    m_name.safe(),m_channel,m_owner);
1210     return true;
1211 }
1212 
1213 // Start echo training
startEchoTrain(unsigned int period)1214 bool ZapDevice::startEchoTrain(unsigned int period)
1215 {
1216     if (!period)
1217 	return true;
1218     if (!ioctl(StartEchoTrain,&period,DebugNote))
1219 	return false;
1220     DDebug(m_owner,DebugAll,"%sEcho train started for %u ms on channel %u [%p]",
1221 	m_name.safe(),period,m_channel,m_owner);
1222     return true;
1223 }
1224 
1225 // Poll for hook events (passive FXO)
pollHook()1226 void ZapDevice::pollHook()
1227 {
1228     if (m_rxHookSig < 0)
1229 	return;
1230 
1231     struct dahdi_params par;
1232     if (!ioctl(GetParams,&par))
1233 	return;
1234 
1235     int rxsig = par.rxhooksig;
1236     if (rxsig != RxSigOnHook)
1237 	rxsig = RxSigOffHook;
1238     if (m_rxHookSig == rxsig)
1239 	return;
1240     // state changed, save the event for later
1241     m_rxHookSig = rxsig;
1242     // states are reversed but that's how Zaptel is...
1243     m_savedEvent = (rxsig == RxSigOnHook) ? DAHDI_EVENT_WINKFLASH : DAHDI_EVENT_ONHOOK;
1244 }
1245 
1246 // Send hook events
sendHook(HookEvent event)1247 bool ZapDevice::sendHook(HookEvent event)
1248 {
1249     const char* name = lookup(event,s_hookEvents);
1250     if (!name) {
1251 	Debug(m_owner,DebugStub,"%sRequest to send unhandled hook event %u [%p]",
1252 	    m_name.safe(),event,this);
1253 	return false;
1254     }
1255 
1256     DDebug(m_owner,DebugAll,"%sSending hook event '%s' on channel %u [%p]",
1257 	m_name.safe(),name,m_channel,m_owner);
1258     return ioctl(SetHook,&event);
1259 }
1260 
1261 // Send DTMFs events using dialing or tone structure
1262 // dtmf: true - send DTMF (tone dialing), false - send MF (pulse dialing)
1263 // op: The dial operation to use
1264 // allDigits: true to send all digits at once
1265 // useTone: Used only if 'allDigits' is false and 'dtmf' is true
sendDtmf(const char * tone,bool dtmf,DialOperation op,bool allDigits,bool useTone)1266 bool ZapDevice::sendDtmf(const char* tone, bool dtmf, DialOperation op,
1267     bool allDigits, bool useTone)
1268 {
1269     XDebug(m_owner,DebugAll,"%ssendDtmf('%s',%u,%u,%u,%u) [%p]",
1270 	m_name.safe(),tone,dtmf,op,allDigits,useTone,this);
1271     if (!(tone && *tone))
1272 	return false;
1273 
1274     struct dahdi_dialoperation dop;
1275     dop.op = op;
1276     dop.dialstr[0] = dtmf ? 'T' : 'P';
1277 
1278     if (allDigits) {
1279 	int len = strlen(tone);
1280 	int maxLen = DAHDI_MAX_DTMF_BUF - 2;
1281 	if (len > maxLen) {
1282 	    Debug(m_owner,DebugNote,
1283 		"%sCan't send DTMF '%s' (len %d greater then max len %d) [%p]",
1284 		m_name.safe(),tone,len,maxLen,this);
1285 	    return false;
1286 	}
1287 	strcpy(dop.dialstr+1,tone);
1288 	DDebug(m_owner,DebugAll,"%sSending DTMF '%s' on channel %u [%p]",
1289 	    m_name.safe(),dop.dialstr,m_channel,this);
1290 	return ioctl(ZapDevice::SetDial,&dop,DebugMild);
1291     }
1292 
1293     if (useTone && dtmf)
1294 	for (; *tone; tone++) {
1295 	    if (!sendDtmf(*tone))
1296 		return false;
1297 	}
1298     else {
1299 	dop.dialstr[2] = 0;
1300 	for (; *tone; tone++) {
1301 	    dop.dialstr[1] = *tone;
1302 	    DDebug(m_owner,DebugAll,"%sSending DTMF '%s' on channel %u [%p]",
1303 		m_name.safe(),dop.dialstr,m_channel,this);
1304 	    if (!ioctl(ZapDevice::SetDial,&dop,DebugMild))
1305 		return false;
1306 	}
1307     }
1308     return true;
1309 }
1310 
1311 // Send DTMF event using tone structure
sendDtmf(char tone)1312 bool ZapDevice::sendDtmf(char tone)
1313 {
1314     XDebug(m_owner,DebugAll,"%ssendDtmf('%c') [%p]",m_name.safe(),tone,this);
1315 #define YZAP_TONES 20
1316     static char tones[YZAP_TONES+1] = "0123456789*#ABCDabcd";
1317     static int zapTones[YZAP_TONES] = {
1318 	DAHDI_TONE_DTMF_0, DAHDI_TONE_DTMF_1, DAHDI_TONE_DTMF_2, DAHDI_TONE_DTMF_3,
1319 	DAHDI_TONE_DTMF_4, DAHDI_TONE_DTMF_5, DAHDI_TONE_DTMF_6, DAHDI_TONE_DTMF_7,
1320 	DAHDI_TONE_DTMF_8, DAHDI_TONE_DTMF_9, DAHDI_TONE_DTMF_s, DAHDI_TONE_DTMF_p,
1321 	DAHDI_TONE_DTMF_A, DAHDI_TONE_DTMF_B, DAHDI_TONE_DTMF_C, DAHDI_TONE_DTMF_D,
1322 	DAHDI_TONE_DTMF_A, DAHDI_TONE_DTMF_B, DAHDI_TONE_DTMF_C, DAHDI_TONE_DTMF_D
1323 	};
1324 
1325     // Get zaptel tone
1326     int zapTone = 0;
1327     for (; zapTone < YZAP_TONES; zapTone++)
1328 	if (tone == tones[zapTone])
1329 	    break;
1330     if (zapTone == YZAP_TONES) {
1331 	Debug(m_owner,DebugNote,"%sCan't send invalid DTMF '%c' on channel %u [%p]",
1332 	    m_name.safe(),tone,m_channel,this);
1333 	return false;
1334     }
1335     DDebug(m_owner,DebugAll,"%sSending DTMF '%c' (%d) on channel %u [%p]",
1336 	m_name.safe(),tone,zapTones[zapTone],m_channel,this);
1337     return ioctl(ZapDevice::SendTone,&zapTones[zapTone],DebugMild);
1338 #undef YZAP_TONES
1339 }
1340 
1341 // Get an event. Return 0 if no events. Set digit if the event is a DTMF/PULSE digit
getEvent(char & digit)1342 int ZapDevice::getEvent(char& digit)
1343 {
1344     int event = m_savedEvent;
1345     if (event)
1346 	m_savedEvent = 0;
1347     else if (!ioctl(GetEvent,&event,DebugMild))
1348 	return 0;
1349     if ((m_zapsig == DAHDI_SIG_EM) && (m_type == FXO)) {
1350 	// For an "E&M FXO" the meanings of on/off hook change
1351 	switch (event) {
1352 	    case OnHook:
1353 		event = OffHookRing;
1354 		break;
1355 	    case OffHookRing:
1356 		event = RingBegin;
1357 		break;
1358 	}
1359     }
1360     if (event & DigitEvent) {
1361 	digit = (char)event;
1362 	event &= DigitEvent;
1363 	XDebug(m_owner	,DebugAll,"%sGot digit event %d '%s'=%c on channel %u [%p]",
1364 	    m_name.safe(),event,lookup(event,s_events),digit,m_channel,m_owner);
1365     }
1366 #ifdef DEBUG
1367     else if (event)
1368 	Debug(m_owner,DebugAll,"%sGot event %d on channel %u [%p]",
1369 	    m_name.safe(),event,m_channel,m_owner);
1370 #endif
1371     return event;
1372 }
1373 
1374 // Get alarms from this device. Return true if alarms changed
checkAlarms()1375 bool ZapDevice::checkAlarms()
1376 {
1377     struct dahdi_spaninfo info;
1378     memset(&info,0,sizeof(info));
1379     info.spanno = m_span;
1380     if (!(ioctl(GetInfo,&info,DebugAll)))
1381 	return false;
1382     if (m_alarms == info.alarms)
1383 	return false;
1384     m_alarms = info.alarms;
1385     m_alarmsText = "";
1386     if (m_alarms) {
1387 	for(int i = 0; s_alarms[i].token; i++)
1388 	    if (m_alarms & s_alarms[i].value) {
1389 		m_alarmsText.append(s_alarms[i].token,",");
1390 		if (s_alarms[i].value == ZapDevice::Yellow || s_alarms[i].value == ZapDevice::Blue) {
1391 		    bool notifStat = false;
1392 		    sendModuleUpdate("alarm",zapName(),notifStat,s_alarms[i].value);
1393 		}
1394 	    }
1395 	Debug(m_owner,DebugNote,"%sAlarms changed (%d,'%s') on channel %u [%p]",
1396 	    m_name.safe(),m_alarms,m_alarmsText.safe(),m_channel,m_owner);
1397     }
1398     return true;
1399 }
1400 
1401 // Reset device's alarms
resetAlarms()1402 void ZapDevice::resetAlarms()
1403 {
1404     m_alarms = 0;
1405     m_alarmsText = "";
1406     Debug(m_owner,DebugInfo,"%sNo more alarms on channel %u [%p]",
1407 	m_name.safe(),m_channel,m_owner);
1408 }
1409 
1410 // Flush read/write buffers
flushBuffers(FlushTarget target)1411 bool ZapDevice::flushBuffers(FlushTarget target)
1412 {
1413     if (!ioctl(FlushBuffers,&target,DebugNote))
1414 	return false;
1415 #ifdef DEBUG
1416     String tmp;
1417     if (target & FlushRead)
1418 	tmp.append("read","/");
1419     if (target & FlushWrite)
1420 	tmp.append("write","/");
1421     if (target & FlushEvent)
1422 	tmp.append("events","/");
1423     DDebug(m_owner,DebugAll,"%sFlushed buffers (%s) on channel %u [%p]",
1424 	m_name.safe(),tmp.c_str(),m_channel,m_owner);
1425 #endif
1426     return true;
1427 }
1428 
1429 // Check if received data. Wait usec microseconds before returning
select(unsigned int usec)1430 bool ZapDevice::select(unsigned int usec)
1431 {
1432     FD_ZERO(&m_rdfds);
1433     FD_SET(m_handle, &m_rdfds);
1434     FD_ZERO(&m_errfds);
1435     FD_SET(m_handle, &m_errfds);
1436     m_tv.tv_sec = 0;
1437     m_tv.tv_usec = usec;
1438     int sel = ::select(m_handle+1,&m_rdfds,NULL,&m_errfds,&m_tv);
1439     if (sel >= 0) {
1440 	m_event = FD_ISSET(m_handle,&m_errfds);
1441 	m_canRead = FD_ISSET(m_handle,&m_rdfds);
1442 	m_selectError = false;
1443 	return true;
1444     }
1445     if (!(canRetry() || m_selectError)) {
1446 	Debug(m_owner,DebugWarn,"%sSelect failed on channel %u. %d: %s [%p]",
1447 	    m_name.safe(),m_channel,errno,::strerror(errno),m_owner);
1448 	m_selectError = true;
1449     }
1450     return false;
1451 }
1452 
recv(void * buffer,int len)1453 int ZapDevice::recv(void* buffer, int len)
1454 {
1455     errno = 0;
1456     int r = ::read(m_handle,buffer,len);
1457     if (r >= 0) {
1458 	m_event = false;
1459 	m_readError = false;
1460 	return r;
1461     }
1462     // The caller should check for events if the error is ELAST
1463     m_event = (errno == ELAST);
1464     if (m_event)
1465 	return -1;
1466     if (!(canRetry() || m_readError)) {
1467 	Debug(m_owner,DebugWarn,"%sRead failed on channel %u. %d: %s [%p]",
1468 	    m_name.safe(),m_channel,errno,::strerror(errno),m_owner);
1469 	m_readError = true;
1470     }
1471     return -1;
1472 }
1473 
send(const void * buffer,int len)1474 int ZapDevice::send(const void* buffer, int len)
1475 {
1476     errno = 0;
1477     int w = ::write(m_handle,buffer,len);
1478     if (w == len) {
1479 	m_writeError = false;
1480 	return w;
1481     }
1482     if (errno == ELAST)
1483 	m_event = true;
1484     else if (!m_writeError) {
1485 	Debug(m_owner,DebugWarn,
1486 	    "%sWrite failed on channel %u (sent %d instead of %d). %d: %s [%p]",
1487 	    m_name.safe(),m_channel,w>=0?w:0,len,errno,::strerror(errno),m_owner);
1488 	m_writeError = true;
1489     }
1490     return (w < 0 ? -1 : w);
1491 }
1492 
1493 // Get driver version and echo canceller
getVersion(NamedList & dest)1494 bool ZapDevice::getVersion(NamedList& dest)
1495 {
1496     struct dahdi_versioninfo info;
1497     if (!ioctl(GetVersion,&info,DebugNote))
1498 	return false;
1499     dest.setParam("version",info.version);
1500     dest.setParam("echocanceller",info.echo_canceller);
1501     return true;
1502 }
1503 
1504 // Get span info
getSpanInfo(int span,NamedList & dest,int * spans)1505 bool ZapDevice::getSpanInfo(int span, NamedList& dest, int* spans)
1506 {
1507     struct dahdi_spaninfo info;
1508     memset(&info,0,sizeof(info));
1509     info.spanno = (span != -1) ? span : m_span;
1510     if (!ioctl(GetInfo,&info,DebugNote))
1511 	return false;
1512     dest.addParam("span",String(span));
1513     dest.addParam("name",info.name);
1514     dest.addParam("desc",info.desc);
1515     dest.addParam("alarms",String(info.alarms));
1516     String alarmsText;
1517     for(int i = 0; s_alarms[i].token; i++)
1518 	if (info.alarms & s_alarms[i].value)
1519 	    alarmsText.append(s_alarms[i].token,",");
1520     dest.addParam("alarmstext",alarmsText);
1521     dest.addParam("configured-chans",String(info.numchans));
1522     dest.addParam("total-chans",String(info.totalchans));
1523     if (spans)
1524 	*spans = info.totalspans;
1525     return true;
1526 }
1527 
1528 // Get channel parameters
getChanParams(NamedList & dest)1529 bool ZapDevice::getChanParams(NamedList& dest)
1530 {
1531     struct dahdi_params par;
1532     if (!ioctl(GetParams,&par))
1533 	return false;
1534     dest.addParam("format",lookup(par.curlaw,s_formats));
1535     dest.addParam("prewinktime",String(par.prewinktime));
1536     dest.addParam("preflashtime",String(par.preflashtime));
1537     dest.addParam("winktime",String(par.winktime));
1538     dest.addParam("flashtime",String(par.flashtime));
1539     dest.addParam("starttime",String(par.starttime));
1540     dest.addParam("rxwinktime",String(par.rxwinktime));
1541     dest.addParam("rxflashtime",String(par.rxflashtime));
1542     dest.addParam("debouncetime",String(par.debouncetime));
1543     dest.addParam("pulsebreaktime",String(par.pulsebreaktime));
1544     dest.addParam("pulsemaketime",String(par.pulsemaketime));
1545     dest.addParam("pulseaftertime",String(par.pulseaftertime));
1546     return true;
1547 }
1548 
1549 // Set/get dial parameters (DTMF/MF length)
dialParams(bool set,int & toneLen,int & mfLen)1550 bool ZapDevice::dialParams(bool set, int& toneLen, int& mfLen)
1551 {
1552     struct dahdi_dialparams dp;
1553     ::memset(&dp,0,sizeof(struct dahdi_dialparams));
1554 
1555     if (!set) {
1556 	if (!ioctl(GetDialParams,&dp,DebugMild))
1557 	    return false;
1558 	toneLen = dp.dtmf_tonelen;
1559 	mfLen = dp.mfv1_tonelen;
1560 	return true;
1561     }
1562 
1563     dp.dtmf_tonelen = toneLen;
1564     dp.mfv1_tonelen = mfLen;
1565     return ioctl(SetDialParams,&dp,DebugNote);
1566 }
1567 
1568 // Make IOCTL requests on this device
ioctl(IoctlRequest request,void * param,int level)1569 bool ZapDevice::ioctl(IoctlRequest request, void* param, int level)
1570 {
1571     if (!param) {
1572 	Debug(&plugin,DebugStub,"ZapDevice::ioctl(). 'param' is missing");
1573 	return false;
1574     }
1575 
1576     int ret = -1;
1577     switch (request) {
1578 	case GetEvent:
1579 	    ret = ::ioctl(m_handle,DAHDI_GETEVENT,param);
1580 	    break;
1581 	case SetChannel:
1582 	    ret = ::ioctl(m_handle,DAHDI_SPECIFY,param);
1583 	    break;
1584 	case SetBlkSize:
1585 	    ret = ::ioctl(m_handle,DAHDI_SET_BLOCKSIZE,param);
1586 	    break;
1587 	case SetBuffers:
1588 	    ret = ::ioctl(m_handle,DAHDI_SET_BUFINFO,param);
1589 	    break;
1590 	case SetFormat:
1591 	    ret = ::ioctl(m_handle,DAHDI_SETLAW,param);
1592 	    break;
1593 	case SetAudioMode:
1594 	    ret = ::ioctl(m_handle,DAHDI_AUDIOMODE,param);
1595 	    break;
1596 	case SetEchoCancel:
1597 	    ret = ::ioctl(m_handle,DAHDI_ECHOCANCEL,param);
1598 	    break;
1599 	case SetDial:
1600 	    ret = ::ioctl(m_handle,DAHDI_DIAL,param);
1601 	    break;
1602 	case SetHook:
1603 	    ret = ::ioctl(m_handle,DAHDI_HOOK,param);
1604 	    break;
1605 	case SetToneDetect:
1606 #ifdef DAHDI_TONEDETECT
1607 	    ret = ::ioctl(m_handle,DAHDI_TONEDETECT,param);
1608 	    break;
1609 #else
1610 	    // Show message only if requested to set tone detection
1611 	    if (param && *param)
1612 		Debug(m_owner,level,"%sIOCTL(%s) failed: unsupported request [%p]",
1613 		    m_name.safe(),lookup(SetToneDetect,s_ioctl_request),m_owner);
1614 	    return false;
1615 #endif
1616 	case SetPolarity:
1617 	    ret = ::ioctl(m_handle,DAHDI_SETPOLARITY,param);
1618 	    break;
1619 	case SetLinear:
1620 	    ret = ::ioctl(m_handle,DAHDI_SETLINEAR,param);
1621 	    break;
1622 	case SetDialParams:
1623 	    ret = ::ioctl(m_handle,DAHDI_SET_DIALPARAMS,param);
1624 	    break;
1625 	case GetParams:
1626 	    ret = ::ioctl(m_handle,DAHDI_GET_PARAMS,param);
1627 	    break;
1628 	case GetInfo:
1629 	    ret = ::ioctl(m_handle,DAHDI_SPANSTAT,param);
1630 	    break;
1631 	case GetDialParams:
1632 	    ret = ::ioctl(m_handle,DAHDI_GET_DIALPARAMS,param);
1633 	    break;
1634 	case StartEchoTrain:
1635 	    ret = ::ioctl(m_handle,DAHDI_ECHOTRAIN,param);
1636 	    break;
1637 	case FlushBuffers:
1638 	    ret = ::ioctl(m_handle,DAHDI_FLUSH,param);
1639 	    break;
1640 	case SendTone:
1641 	    ret = ::ioctl(m_handle,DAHDI_SENDTONE,param);
1642 	    break;
1643 	case GetVersion:
1644 	    ret = ::ioctl(m_handle,DAHDI_GETVERSION,param);
1645 	    break;
1646     }
1647     if (!ret || errno == EINPROGRESS) {
1648 	if (errno == EINPROGRESS)
1649 	    DDebug(m_owner,DebugAll,"%sIOCTL(%s) in progress on channel %u (param=%d) [%p]",
1650 		m_name.safe(),lookup(request,s_ioctl_request),
1651 		m_channel,*(int*)param,m_owner);
1652 #ifdef XDEBUG
1653 	else if (request != GetEvent)
1654 	    Debug(m_owner,DebugAll,"%sIOCTL(%s) succedded on channel %u (param=%d) [%p]",
1655 		m_name.safe(),lookup(request,s_ioctl_request),
1656 		m_channel,*(int*)param,m_owner);
1657 #endif
1658 	return true;
1659     }
1660     Debug(m_owner,level,"%sIOCTL(%s) failed on channel %u (param=%d). %d: %s [%p]",
1661 	m_name.safe(),lookup(request,s_ioctl_request),
1662 	m_channel,*(int*)param,errno,::strerror(errno),m_owner);
1663     return false;
1664 }
1665 
1666 
1667 /**
1668  * ZapInterface
1669  */
ZapInterface(const NamedList & params)1670 ZapInterface::ZapInterface(const NamedList& params)
1671     : SignallingComponent(params,&params,"tdm"),
1672       m_device(ZapDevice::DChan,this,0,0),
1673       m_priority(Thread::Normal),
1674       m_errorMask(255),
1675       m_numbufs(16), m_bufsize(1024), m_buffer(0),
1676       m_readOnly(false), m_sendReadOnly(false),
1677       m_notify(0),
1678       m_timerRxUnder(0)
1679 {
1680     m_buffer = new unsigned char[m_bufsize + ZAP_CRC_LEN];
1681     XDebug(this,DebugAll,"ZapInterface::ZapInterface() [%p]",this);
1682 }
1683 
~ZapInterface()1684 ZapInterface::~ZapInterface()
1685 {
1686     cleanup(false);
1687     delete[] m_buffer;
1688     XDebug(this,DebugAll,"ZapInterface::~ZapInterface() [%p]",this);
1689 }
1690 
1691 // Called by the factory to create Zaptel interfaces or spans
create(const String & type,NamedList & name)1692 SignallingComponent* ZapInterface::create(const String& type, NamedList& name)
1693 {
1694     bool circuit = true;
1695     if (type == "SignallingInterface")
1696 	circuit = false;
1697     else if (type == "SignallingCircuitSpan")
1698 	;
1699     else
1700 	return 0;
1701 
1702     TempObjectCounter cnt(plugin.objectsCounter());
1703     const String* module = name.getParam("module");
1704     if (module && *module != "zapcard")
1705 	return 0;
1706     Configuration cfg(Engine::configFile("zapcard"));
1707     const char* sectName = name.getValue((circuit ? "voice" : "sig"),name.getValue("basename",name));
1708     NamedList* config = cfg.getSection(sectName);
1709 
1710     if (!name.getBoolValue(YSTRING("local-config"),false))
1711 	config = &name;
1712     else if (!config) {
1713 	DDebug(&plugin,DebugConf,"No section '%s' in configuration",c_safe(sectName));
1714 	return 0;
1715     } else
1716 	name.copyParams(*config);
1717 
1718 #ifdef DEBUG
1719     if (plugin.debugAt(DebugAll)) {
1720 	String tmp;
1721 	name.dump(tmp,"\r\n  ",'\'',true);
1722 	Debug(&plugin,DebugAll,"ZapInterface::create %s%s",
1723 	    (circuit ? "span" : "interface"),tmp.c_str());
1724     }
1725 #endif
1726     String sDevType = config->getValue("type");
1727     ZapDevice::Type devType = (ZapDevice::Type)lookup(sDevType,s_types,ZapDevice::E1);
1728 
1729     NamedList dummy("general");
1730     NamedList* general = cfg.getSection("general");
1731     if (!general)
1732 	general = &dummy;
1733 
1734     String sOffset = config->getValue("offset");
1735     unsigned int offset = (unsigned int)sOffset.toInteger(-1);
1736     if (offset == (unsigned int)-1) {
1737 	Debug(&plugin,DebugWarn,"Section '%s'. Invalid offset='%s'",
1738 	    config->c_str(),sOffset.safe());
1739 	return 0;
1740     }
1741 
1742     if (circuit) {
1743 	ZapSpan* span = new ZapSpan(name);
1744 	bool ok = false;
1745 	if (span->group())
1746 	    ok = span->init(devType,offset,*config,*general,name);
1747 	else
1748 	    Debug(&plugin,DebugWarn,"Can't create span '%s'. Group is missing",
1749 		span->id().safe());
1750 	if (ok)
1751 	    return span;
1752 	TelEngine::destruct(span);
1753 	return 0;
1754     }
1755 
1756     // Check span type
1757     if (devType != ZapDevice::E1 && devType != ZapDevice::T1 && devType != ZapDevice::BRI) {
1758 	Debug(&plugin,DebugWarn,"Section '%s'. Can't create D-channel for type='%s'",
1759 	    config->c_str(),sDevType.c_str());
1760 	return 0;
1761     }
1762     // Check channel
1763     String sig = config->getValue("sigchan");
1764     unsigned int count = (devType == ZapDevice::E1 ? 31 : 24);
1765     if (sig.null()) {
1766 	switch (devType) {
1767 	    case ZapDevice::E1:
1768 		sig = 16;
1769 		break;
1770 	    case ZapDevice::T1:
1771 		sig = 24;
1772 		break;
1773 	    case ZapDevice::BRI:
1774 		sig = 3;
1775 		break;
1776 	    default:
1777 		break;
1778 	}
1779     }
1780     unsigned int code = (unsigned int)sig.toInteger(0);
1781     if (!(sig && code && code <= count)) {
1782 	Debug(&plugin,DebugWarn,"Section '%s'. Invalid sigchan='%s' for type='%s'",
1783 	    config->c_str(),sig.safe(),sDevType.c_str());
1784 	return 0;
1785     }
1786     ZapInterface* iface = new ZapInterface(name);
1787     if (iface->init(devType,code,offset+code,*config,*general,name))
1788 	return iface;
1789     TelEngine::destruct(iface);
1790     return 0;
1791 }
1792 
init(ZapDevice::Type type,unsigned int code,unsigned int channel,const NamedList & config,const NamedList & defaults,const NamedList & params)1793 bool ZapInterface::init(ZapDevice::Type type, unsigned int code, unsigned int channel,
1794 	const NamedList& config, const NamedList& defaults, const NamedList& params)
1795 {
1796     TempObjectCounter cnt(plugin.objectsCounter());
1797     m_device.channel(channel,code);
1798     m_readOnly = getBoolValue("readonly",config,defaults,params);
1799     m_priority = Thread::priority(config.getValue("priority",defaults.getValue("priority")));
1800     int rx = params.getIntValue("rxunderrun");
1801     if (rx > 0)
1802 	m_timerRxUnder.interval(rx);
1803     int i = params.getIntValue("errormask",config.getIntValue("errormask",255));
1804     m_errorMask = ((i >= 0 && i < 256) ? i : 255);
1805     if (debugAt(DebugInfo)) {
1806 	String s;
1807 	s << "driver=" << plugin.debugName();
1808 	s << " section=" << config.c_str();
1809 	s << " type=" << lookup(type,s_types);
1810 	s << " channel=" << channel;
1811 	s << " errormask=" << (unsigned int)m_errorMask;
1812 	s << " readonly=" << String::boolText(m_readOnly);
1813 	s << " rxunderruninterval=" << (unsigned int)m_timerRxUnder.interval() << " ms";
1814 	s << " numbufs=" << (unsigned int)m_numbufs;
1815 	s << " bufsize=" << (unsigned int)m_bufsize;
1816 	s << " priority=" << Thread::priority(m_priority);
1817 	Debug(this,DebugInfo,"D-channel: %s [%p]",s.c_str(),this);
1818     }
1819     m_down = false;
1820     return true;
1821 }
1822 
1823 // Process incoming data
process()1824 bool ZapInterface::process()
1825 {
1826     if (!m_device.select(100))
1827 	return false;
1828     if (!m_device.canRead()) {
1829 	if (m_device.event())
1830 	    checkEvents();
1831 	return false;
1832     }
1833 
1834     int r = m_device.recv(m_buffer,m_bufsize + ZAP_CRC_LEN);
1835     if (r == -1) {
1836 	if (m_device.event())
1837 	    checkEvents();
1838 	return false;
1839     }
1840     if (r < ZAP_CRC_LEN + 1) {
1841 	Debug(this,DebugMild,"Short read %u bytes (with CRC) [%p]",r,this);
1842 	return false;
1843     }
1844 
1845     s_ifaceNotifyMutex.lock();
1846     m_notify = 0;
1847     s_ifaceNotifyMutex.unlock();
1848     DataBlock packet(m_buffer,r - ZAP_CRC_LEN,false);
1849 #ifdef XDEBUG
1850     String hex;
1851     hex.hexify(packet.data(),packet.length(),' ');
1852     Debug(this,DebugAll,"Received data: %s [%p]",hex.safe(),this);
1853 #endif
1854     receivedPacket(packet);
1855     packet.clear(false);
1856     return true;
1857 }
1858 
getObject(const String & name) const1859 void* ZapInterface::getObject(const String& name) const
1860 {
1861     if (name == "ZapInterface")
1862 	return (void*)this;
1863     return SignallingInterface::getObject(name);
1864 }
1865 
1866 // Send signalling packet
transmitPacket(const DataBlock & packet,bool repeat,PacketType type)1867 bool ZapInterface::transmitPacket(const DataBlock& packet, bool repeat, PacketType type)
1868 {
1869     static DataBlock crc(0,ZAP_CRC_LEN);
1870 
1871     if (m_readOnly) {
1872 	if (!m_sendReadOnly)
1873 	    Debug(this,DebugWarn,"Attempt to send data on read only interface");
1874 	m_sendReadOnly = true;
1875 	return false;
1876     }
1877     if (!m_device.valid())
1878 	return false;
1879 
1880 #ifdef XDEBUG
1881     String hex;
1882     hex.hexify(packet.data(),packet.length(),' ');
1883     Debug(this,DebugAll,"Sending data: %s [%p]",hex.safe(),this);
1884 #endif
1885     DataBlock pkt(packet);
1886     // zaptel needs the extra space to write the CRC there
1887     pkt += crc;
1888     return m_device.send(pkt.data(),pkt.length());
1889 }
1890 
1891 // Interface control. Open device and start worker when enabled, cleanup when disabled
control(Operation oper,NamedList * params)1892 bool ZapInterface::control(Operation oper, NamedList* params)
1893 {
1894     DDebug(this,DebugAll,"Control with oper=%u [%p]",oper,this);
1895     switch (oper) {
1896 	case Enable:
1897 	case Disable:
1898 	    break;
1899 	case EnableTx:
1900 	case DisableTx:
1901 	    if (m_readOnly == (oper == DisableTx))
1902 		return TelEngine::controlReturn(params,true);
1903 	    m_readOnly = (oper == DisableTx);
1904 	    m_sendReadOnly = false;
1905 	    Debug(this,DebugInfo,"Tx is %sabled [%p]",m_readOnly?"dis":"en",this);
1906 	    return TelEngine::controlReturn(params,true);
1907 	case Query:
1908 	    return TelEngine::controlReturn(params,valid());
1909 	default:
1910 	    return SignallingInterface::control(oper,params);
1911     }
1912     if (oper == Enable) {
1913 	if (valid())
1914 	    return TelEngine::controlReturn(params,true);
1915 	bool ok = m_device.valid() || m_device.open(m_numbufs,m_bufsize);
1916 	if (ok)
1917 	    ok = ZapWorkerClient::start(m_priority,this,debugName());
1918 	if (ok) {
1919 	    Debug(this,DebugAll,"Enabled [%p]",this);
1920 	    m_timerRxUnder.start();
1921 	}
1922 	else {
1923 	    Debug(this,DebugWarn,"Enable failed [%p]",this);
1924 	    control(Disable,0);
1925 	}
1926 	return TelEngine::controlReturn(params,ok);
1927     }
1928     // oper is Disable
1929     bool ok = valid();
1930     m_timerRxUnder.stop();
1931     ZapWorkerClient::stop();
1932     m_device.close();
1933     if (ok)
1934 	Debug(this,DebugAll,"Disabled [%p]",this);
1935     return TelEngine::controlReturn(params,true);
1936 }
1937 
1938 // Check if received any data in the last interval. Notify receiver
timerTick(const Time & when)1939 void ZapInterface::timerTick(const Time& when)
1940 {
1941     if (!m_timerRxUnder.timeout(when.msec()))
1942 	return;
1943     s_ifaceNotifyMutex.lock();
1944     if (m_notify) {
1945 	if (m_notify == 1) {
1946 	    DDebug(this,DebugMild,"RX idle for " FMT64 "ms. Notifying receiver [%p]",
1947 		m_timerRxUnder.interval(),this);
1948 	    notify(RxUnderrun);
1949 	    m_notify = 2;
1950 	}
1951     }
1952     else
1953 	m_notify = 1;
1954     s_ifaceNotifyMutex.unlock();
1955     m_timerRxUnder.start(when.msec());
1956 }
1957 
checkEvents()1958 void ZapInterface::checkEvents()
1959 {
1960     char c = 0;
1961     int event = m_device.getEvent(c);
1962     if (!event)
1963 	return;
1964     int level = DebugWarn;
1965     switch (event) {
1966 	case ZapDevice::Alarm:
1967 	case ZapDevice::NoAlarm:
1968 	    if (event == ZapDevice::Alarm) {
1969 		m_device.checkAlarms();
1970 		Debug(this,DebugNote,"Alarms changed '%s' [%p]",
1971 		    m_device.alarmsText().safe(),this);
1972 		notify(LinkDown);
1973 		sendModuleUpdate("interfaceDown",m_device.zapName(),m_down,LinkDown);
1974 	    }
1975 	    else {
1976 		m_device.resetAlarms();
1977 		DDebug(this,DebugInfo,"No more alarms [%p]",this);
1978 		notify(LinkUp);
1979 		sendModuleUpdate("interfaceUp",m_device.zapName(),m_down,LinkUp);
1980 	    }
1981 	    return;
1982 	case ZapDevice::HdlcAbort:
1983 	    if (m_errorMask & ZAP_ERR_ABORT)
1984 		notify(AlignError);
1985 	    break;
1986 	case ZapDevice::HdlcOverrun:
1987 	    if (m_errorMask & ZAP_ERR_OVERRUN)
1988 		notify(RxOverflow);
1989 	    break;
1990 	case ZapDevice::PulseDigit:
1991 	case ZapDevice::DtmfDown:
1992 	case ZapDevice::DtmfUp:
1993 	    Debug(this,DebugNote,"Got DTMF event '%s' on D-channel [%p]",
1994 		lookup(event,s_events,""),this);
1995 	    return;
1996 	default:
1997 	    level = DebugStub;
1998     }
1999     DDebug(this,level,"Got event %d ('%s') [%p]",event,lookup(event,s_events,""),this);
2000 }
2001 
2002 
2003 /**
2004  * ZapSpan
2005  */
2006 // Create circuits
init(ZapDevice::Type type,unsigned int offset,const NamedList & config,const NamedList & defaults,const NamedList & params)2007 bool ZapSpan::init(ZapDevice::Type type, unsigned int offset,
2008 	const NamedList& config, const NamedList& defaults, const NamedList& params)
2009 {
2010     TempObjectCounter cnt(plugin.objectsCounter());
2011     String voice = config.getValue("voicechans");
2012     unsigned int chans = 0;
2013     bool digital = true;
2014     switch (type) {
2015 	case ZapDevice::E1:
2016 	    if (!voice)
2017 		voice = "1-15.17-31";
2018 	    chans = 31;
2019 	    m_increment = 32;
2020 	    break;
2021 	case ZapDevice::T1:
2022 	    if (!voice)
2023 		voice = "1-23";
2024 	    chans = 24;
2025 	    m_increment = 24;
2026 	    break;
2027 	case ZapDevice::BRI:
2028 	    if (!voice)
2029 		voice = "1-2";
2030 	    chans = 3;
2031 	    m_increment = 3;
2032 	    break;
2033 	case ZapDevice::FXO:
2034 	case ZapDevice::FXS:
2035 	    digital = false;
2036 	    if (!voice)
2037 		voice = "1";
2038 	    chans = (unsigned int)-1;
2039 	    break;
2040 	default:
2041 	    Debug(m_group,DebugStub,
2042 		"ZapSpan('%s'). Can't create circuits for type=%s [%p]",
2043 		id().safe(),lookup(type,s_types),this);
2044 	    return false;
2045     }
2046     unsigned int count = 0;
2047     unsigned int* cics = SignallingUtils::parseUIntArray(voice,1,chans,count,true);
2048     if (!cics) {
2049 	Debug(m_group,DebugWarn,
2050 	    "ZapSpan('%s'). Invalid voicechans='%s' (type=%s,chans=%u) [%p]",
2051 	    id().safe(),voice.safe(),lookup(type,s_types),chans,this);
2052 	return false;
2053     }
2054 
2055     if (!digital)
2056 	m_increment = chans = count;
2057     m_increment = config.getIntValue("increment",m_increment);
2058     unsigned int start = config.getIntValue("start",params.getIntValue("start",0));
2059 
2060     // Create and insert circuits
2061     unsigned int added = 0;
2062     DDebug(m_group,DebugAll,
2063 	"ZapSpan('%s'). Creating circuits starting with %u [%p]",
2064 	id().safe(),start,this);
2065     for (unsigned int i = 0; i < count; i++) {
2066 	unsigned int code = start + cics[i];
2067 	unsigned int channel = offset + cics[i];
2068 	ZapCircuit* cic = 0;
2069 	DDebug(m_group,DebugAll,
2070 	    "ZapSpan('%s'). Creating circuit code=%u channel=%u [%p]",
2071 	    id().safe(),code,channel,this);
2072 	if (digital)
2073 	    cic = new ZapCircuit(type,code,channel,this,config,defaults,params);
2074 	else
2075 	    cic = new ZapAnalogCircuit(type,code,channel,this,config,defaults,params);
2076 	if (m_group->insert(cic)) {
2077 	    added++;
2078 	    continue;
2079 	}
2080 	TelEngine::destruct(cic);
2081 	Debug(m_group,DebugConf,
2082 	    "ZapSpan('%s'). Duplicate circuit code=%u (channel=%u) [%p]",
2083 	    id().safe(),code,channel,this);
2084     }
2085     if (!added) {
2086 	Debug(m_group,DebugWarn,"ZapSpan('%s'). No circuits inserted for this span [%p]",
2087 	    id().safe(),this);
2088 	delete[] cics;
2089 	return false;
2090     }
2091 
2092     if (m_group && m_group->debugAt(DebugInfo)) {
2093 	String s;
2094 	s << "driver=" << plugin.debugName();
2095 	s << " section=" << config.c_str();
2096 	s << " type=" << lookup(type,s_types);
2097 	String c,ch;
2098 	for (unsigned int i = 0; i < count; i++) {
2099 	    c.append(String(start+cics[i]),",");
2100 	    ch.append(String(offset+cics[i]),",");
2101 	}
2102 	s << " channels=" << ch;
2103 	s << " circuits=" << c;
2104 	Debug(m_group,DebugInfo,"ZapSpan('%s') %s [%p]",id().safe(),s.c_str(),this);
2105     }
2106     delete[] cics;
2107     return true;
2108 }
2109 
2110 
2111 /**
2112  * ZapCircuit
2113  */
ZapCircuit(ZapDevice::Type type,unsigned int code,unsigned int channel,ZapSpan * span,const NamedList & config,const NamedList & defaults,const NamedList & params)2114 ZapCircuit::ZapCircuit(ZapDevice::Type type, unsigned int code, unsigned int channel,
2115 	ZapSpan* span, const NamedList& config, const NamedList& defaults,
2116 	const NamedList& params)
2117     : SignallingCircuit(TDM,code,Idle,span->group(),span),
2118     m_device(type,span->group(),channel,code),
2119     m_format(ZapDevice::Alaw),
2120     m_echoCancel(false),
2121     m_crtEchoCancel(false),
2122     m_echoTaps(0),
2123     m_echoTrain(400),
2124     m_dtmfDetect(false),
2125     m_crtDtmfDetect(false),
2126     m_canSend(true),
2127     m_idleValue(255),
2128     m_priority(Thread::Normal),
2129     m_source(0),
2130     m_consumer(0),
2131     m_buflen(0),
2132     m_consBufMax(0),
2133     m_consErrors(0),
2134     m_consErrorBytes(0),
2135     m_consTotal(0),
2136     m_errno(0)
2137 {
2138     m_dtmfDetect = config.getBoolValue("dtmfdetect",true);
2139     if (m_dtmfDetect && ZapDevice::SetToneDetect > 100) {
2140 	Debug(group(),DebugWarn,
2141 	    "ZapCircuit(%u). DTMF detection is not supported by hardware [%p]",
2142 	    code,this);
2143 	m_dtmfDetect = false;
2144     }
2145     m_crtDtmfDetect = m_dtmfDetect;
2146     int tmp = config.getIntValue("echotaps",defaults.getIntValue("echotaps",0));
2147     m_echoTaps = tmp >= 0 ? tmp : 0;
2148     m_crtEchoCancel = m_echoCancel = m_echoTaps;
2149     tmp = (unsigned int)config.getIntValue("echotrain",defaults.getIntValue("echotrain",400));
2150     m_echoTrain = tmp >= 0 ? tmp : 0;
2151     m_canSend = !getBoolValue("readonly",config,defaults,params);
2152     m_buflen = (unsigned int)config.getIntValue("buflen",defaults.getIntValue("buflen",160));
2153     if (!m_buflen)
2154 	m_buflen = 160;
2155     m_consBufMax = m_buflen * 4;
2156     m_sourceBuffer.assign(0,m_buflen);
2157     m_idleValue = defaults.getIntValue("idlevalue",0xff);
2158     m_idleValue = params.getIntValue("idlevalue",config.getIntValue("idlevalue",m_idleValue));
2159     m_priority = Thread::priority(config.getValue("priority",defaults.getValue("priority")));
2160 
2161     switch (type) {
2162 	case ZapDevice::E1:
2163 	case ZapDevice::BRI:
2164 	    m_format = ZapDevice::Alaw;
2165 	    break;
2166 	case ZapDevice::T1:
2167 	    m_format = ZapDevice::Mulaw;
2168 	    break;
2169 	case ZapDevice::FXO:
2170 	    if (getBoolValue("trackhook",config,defaults,params)) {
2171 		if (m_canSend)
2172 		    Debug(group(),DebugNote,"ZapCircuit(%u): Hook tracking for active FXO [%p]",code,this);
2173 		m_device.initHook();
2174 	    }
2175 	    // fall through
2176 	case ZapDevice::FXS:
2177 	    {
2178 		const char* f = config.getValue("format",defaults.getValue("format"));
2179 		m_format = (ZapDevice::Format)lookup(f,s_formats,ZapDevice::Mulaw);
2180 		if (m_format != ZapDevice::Alaw && m_format != ZapDevice::Mulaw)
2181 		    m_format = ZapDevice::Mulaw;
2182 	    }
2183 	    break;
2184 	default:
2185 	    Debug(group(),DebugStub,"ZapCircuit(%u). Unhandled circuit type=%d [%p]",
2186 		code,type,this);
2187     }
2188 
2189     if (group() && group()->debugAt(DebugAll)) {
2190 	String s;
2191 	s << "driver=" << plugin.debugName();
2192 	s << " type=" << lookup(type,s_types);
2193 	s << " channel=" << channel;
2194 	s << " cic=" << code;
2195 	s << " dtmfdetect=" << String::boolText(m_dtmfDetect);
2196 	s << " echotaps=" << m_echoTaps;
2197 	s << " echotrain=" << m_echoTrain;
2198 	s << " buflen=" << m_buflen;
2199 	s << " readonly=" << String::boolText(!m_canSend);
2200 	s << " idlevalue=" << (unsigned int)m_idleValue;
2201 	s << " priority=" << Thread::priority(m_priority);
2202 	Debug(group(),DebugAll,"ZapCircuit %s [%p]",s.c_str(),this);
2203     }
2204 }
2205 
2206 // Change circuit status. Clear events on status change
2207 // New status is Connect: Open device. Create source/consumer. Start worker
2208 // Cleanup on disconnect
status(Status newStat,bool sync)2209 bool ZapCircuit::status(Status newStat, bool sync)
2210 {
2211     if (SignallingCircuit::status() == newStat)
2212 	return true;
2213     if (SignallingCircuit::status() == Missing) {
2214 	Debug(group(),DebugNote,
2215 	    "ZapCircuit(%u). Can't change status to '%s'. Circuit is missing [%p]",
2216 	    code(),lookupStatus(newStat),this);
2217 	return false;
2218     }
2219     TempObjectCounter cnt(plugin.objectsCounter());
2220     Status oldStat = SignallingCircuit::status();
2221     // Allow status change for the following values
2222     switch (newStat) {
2223 	case Missing:
2224 	case Disabled:
2225 	case Idle:
2226 	case Reserved:
2227 	case Connected:
2228 	    if (!SignallingCircuit::status(newStat,sync))
2229 		return false;
2230 	    clearEvents();
2231 	    if (!Engine::exiting())
2232 		DDebug(group(),DebugAll,"ZapCircuit(%u). Changed status to '%s' [%p]",
2233 		    code(),lookupStatus(newStat),this);
2234 	    if (newStat == Connected)
2235 		break;
2236 	    if (oldStat == Connected)
2237 		cleanup(false,newStat);
2238 	    return true;
2239 	default: ;
2240 	    Debug(group(),DebugStub,
2241 		"ZapCircuit(%u). Can't change status to unhandled value %u [%p]",
2242 		code(),newStat,this);
2243 	    return false;
2244     }
2245     // Connected: open device, create source/consumer, start worker
2246     while (true) {
2247 	if (!m_device.open(0,m_buflen))
2248 	    break;
2249 	m_device.flushBuffers();
2250 	setFormat(m_format);
2251 	createData();
2252 	String addr;
2253 	if (group())
2254 	    addr << group()->debugName() << "/";
2255 	addr << code();
2256 	if (!ZapWorkerClient::start(m_priority,group(),addr))
2257 	    break;
2258 	return true;
2259     }
2260     // Rollback on error
2261     cleanup(false,oldStat);
2262     return false;
2263 }
2264 
2265 // Update data format for zaptel device and source/consumer
updateFormat(const char * format,int direction)2266 bool ZapCircuit::updateFormat(const char* format, int direction)
2267 {
2268     s_sourceAccessMutex.lock();
2269     RefPointer<ZapSource> src = m_source;
2270     s_sourceAccessMutex.unlock();
2271 
2272     if (!(src && format && *format))
2273 	return false;
2274     // Do nothing if format is the same
2275     if (src->getFormat() == format && m_consumer && m_consumer->getFormat() == format)
2276 	return false;
2277     TempObjectCounter cnt(plugin.objectsCounter());
2278     // Check format
2279     // T1,E1: allow alaw or mulaw
2280     int f = lookup(format,s_formats,-2);
2281     switch (m_device.type()) {
2282 	case ZapDevice::E1:
2283 	case ZapDevice::T1:
2284 	case ZapDevice::BRI:
2285 	case ZapDevice::FXS:
2286 	case ZapDevice::FXO:
2287 	    if (f == ZapDevice::Alaw || f == ZapDevice::Mulaw)
2288 		break;
2289 	    // Fallthrough to deny format change
2290 	default:
2291 	    Debug(group(),DebugNote,
2292 		"ZapCircuit(%u). Can't set format to '%s' for type=%s [%p]",
2293 		code(),format,lookup(m_device.type(),s_types),this);
2294 	    return false;
2295     }
2296     // Update the format for Zaptel device
2297     if (setFormat((ZapDevice::Format)f)) {
2298 	src->changeFormat(format);
2299 	if (m_consumer)
2300 	    m_consumer->changeFormat(format);
2301 	return true;
2302     }
2303     Debug(group(),DebugNote,
2304 	"ZapCircuit(%u). Failed to update data format to '%s' [%p]",
2305 	code(),format,this);
2306     return false;
2307 }
2308 
2309 // Setup echo canceller or start echo canceller training
setParam(const String & param,const String & value)2310 bool ZapCircuit::setParam(const String& param, const String& value)
2311 {
2312     TempObjectCounter cnt(plugin.objectsCounter());
2313     if (param == "echotrain") {
2314 	int tmp = value.toInteger(-1);
2315 	if (tmp >= 0)
2316 	    m_echoTrain = tmp;
2317 	return m_device.valid() && m_crtEchoCancel && m_device.startEchoTrain(m_echoTrain);
2318     }
2319     if (param == "echocancel") {
2320 	if (!value.isBoolean())
2321 	    return false;
2322 	bool tmp = value.toBoolean();
2323 	if (tmp == m_crtEchoCancel)
2324 	    return true;
2325 	if (m_echoTaps)
2326 	    m_crtEchoCancel = tmp;
2327 	else if (tmp)
2328 	    return false;
2329 	else
2330 	    m_crtEchoCancel = false;
2331 	if (!m_device.valid())
2332 	    return false;
2333 	bool ok = m_device.setEchoCancel(m_crtEchoCancel,m_echoTaps);
2334 	if (m_crtEchoCancel)
2335 	    m_crtEchoCancel = ok;
2336 	return ok;
2337     }
2338     if (param == "echotaps") {
2339 	int tmp = value.toInteger();
2340 	m_echoTaps = tmp >= 0 ? tmp : 0;
2341 	return true;
2342     }
2343     if (param == "tonedetect") {
2344 	bool tmp = value.toBoolean();
2345 	if (tmp == m_crtDtmfDetect)
2346 	    return true;
2347 	m_crtDtmfDetect = tmp;
2348 	if (!m_device.valid())
2349 	    return true;
2350 	bool ok = m_device.setDtmfDetect(m_crtDtmfDetect);
2351 	if (m_crtDtmfDetect)
2352 	    m_crtDtmfDetect = ok;
2353 	return ok;
2354     }
2355     if (param == "special_mode") {
2356 	m_specialMode = value;
2357 	return true;
2358     }
2359     return false;
2360 }
2361 
2362 // Get circuit data
getParam(const String & param,String & value) const2363 bool ZapCircuit::getParam(const String& param, String& value) const
2364 {
2365     TempObjectCounter cnt(plugin.objectsCounter());
2366     if (param == "buflen")
2367 	value = m_buflen;
2368     else if (param == "tonedetect")
2369 	value = String::boolText(m_crtDtmfDetect);
2370     else if (param == "channel")
2371 	value = m_device.channel();
2372     else if (param == "echocancel")
2373 	value = String::boolText(m_crtEchoCancel);
2374     else if (param == "echotaps")
2375 	value = m_echoTaps;
2376     else if (param == "alarms")
2377 	value = m_device.alarmsText();
2378     else if (param == "driver")
2379 	value = plugin.debugName();
2380     else
2381 	return false;
2382     return true;
2383 }
2384 
2385 // Get source or consumer
getObject(const String & name) const2386 void* ZapCircuit::getObject(const String& name) const
2387 {
2388     if (name == "ZapCircuit")
2389 	return (void*)this;
2390     if (SignallingCircuit::status() == Connected) {
2391 	if (name == "DataSource")
2392 	    return m_source;
2393 	if (name == "DataConsumer")
2394 	    return m_consumer;
2395     }
2396     return SignallingCircuit::getObject(name);
2397 }
2398 
2399 // Process incoming data
process()2400 bool ZapCircuit::process()
2401 {
2402     s_sourceAccessMutex.lock();
2403     RefPointer<ZapSource> src = m_source;
2404     s_sourceAccessMutex.unlock();
2405 
2406     if (!(m_device.valid() && SignallingCircuit::status() == Connected && src))
2407 	return false;
2408 
2409     if (!m_device.select(10))
2410 	return false;
2411     if (!m_device.canRead()) {
2412 	if (m_device.event())
2413 	    checkEvents();
2414 	return false;
2415     }
2416 
2417     int r = m_device.recv(m_sourceBuffer.data(),m_sourceBuffer.length());
2418     if (m_device.event())
2419 	checkEvents();
2420     if (r > 0) {
2421 	if ((unsigned int)r != m_sourceBuffer.length())
2422 	    ::memset((unsigned char*)m_sourceBuffer.data() + r,m_idleValue,m_sourceBuffer.length() - r);
2423 	src->Forward(m_sourceBuffer);
2424 	return true;
2425     }
2426     return false;
2427 }
2428 
2429 // Send an event through the circuit
sendEvent(SignallingCircuitEvent::Type type,NamedList * params)2430 bool ZapCircuit::sendEvent(SignallingCircuitEvent::Type type, NamedList* params)
2431 {
2432     XDebug(group(),DebugAll,"ZapCircuit(%u). sendEvent(%u) [%p]",code(),type,this);
2433     if (!m_canSend)
2434 	return false;
2435     TempObjectCounter cnt(plugin.objectsCounter());
2436 
2437     if (type == SignallingCircuitEvent::Dtmf) {
2438 	const char* tones = 0;
2439 	bool dtmf = true;
2440 	bool dial = true;
2441 	if (params) {
2442 	    tones = params->getValue("tone");
2443 	    dtmf = !params->getBoolValue("pulse",false);
2444 	    dial = params->getBoolValue("dial",true);
2445 	}
2446 	if (dial)
2447 	    return m_device.sendDtmf(tones,dtmf,ZapDevice::DialReplace,true,false);
2448 	return m_device.sendDtmf(tones,dtmf,ZapDevice::DialAppend,false,true);
2449     }
2450 
2451     Debug(group(),DebugNote,"ZapCircuit(%u). Unable to send unknown event %u [%p]",
2452 	code(),type,this);
2453     return false;
2454 }
2455 
2456 // Consume data sent by the consumer
consume(const DataBlock & data)2457 void ZapCircuit::consume(const DataBlock& data)
2458 {
2459     if (!(SignallingCircuit::status() >= Special && m_canSend && data.length()))
2460 	return;
2461 
2462     // Copy data in buffer
2463     // Throw old data on buffer overrun
2464     m_consTotal += data.length();
2465     if (m_consBuffer.length() + data.length() <= m_consBufMax)
2466 	m_consBuffer += data;
2467     else {
2468 	Debug(group(),DebugAll,
2469 	    "ZapCircuit(%u). Buffer overrun old=%u channel=%u (%d: %s) [%p]",
2470 	    code(),m_consBuffer.length(),m_device.channel(),m_errno,
2471 	    ::strerror(m_errno),this);
2472 	m_consErrors++;
2473 	m_consErrorBytes += m_consBuffer.length();
2474 	m_consBuffer = data;
2475     }
2476 
2477     // Send buffer. Stop on error
2478     while (m_consBuffer.length() >= m_buflen) {
2479 	int w = m_device.write(m_consBuffer.data(),m_buflen);
2480 	if (w <= 0) {
2481 	    m_errno = errno;
2482 	    break;
2483 	}
2484 	m_errno = 0;
2485 	m_consBuffer.cut(-w);
2486 	XDebug(group(),DebugAll,"ZapCircuit(%u). Sent %d bytes. Remaining: %u [%p]",
2487 	    code(),w,m_consBuffer.length(),this);
2488     }
2489 }
2490 
2491 // Close device. Stop worker. Remove source consumer. Change status. Release memory if requested
2492 // Reset echo canceller and tone detector if the device is not closed
cleanup(bool release,Status stat,bool stop)2493 void ZapCircuit::cleanup(bool release, Status stat, bool stop)
2494 {
2495     if (stop || release) {
2496 	ZapWorkerClient::stop();
2497 	m_device.close();
2498     }
2499     if (m_consumer) {
2500 	if (m_consErrors)
2501 	    Debug(group(),DebugNote,
2502 		"ZapCircuit(%u). Consumer errors: %u. Lost: %u/%u [%p]",
2503 		code(),m_consErrors,m_consErrorBytes,m_consTotal,this);
2504 	TelEngine::destruct(m_consumer);
2505     }
2506     if (m_source) {
2507 	s_sourceAccessMutex.lock();
2508 	ZapSource* tmp = m_source;
2509 	m_source = 0;
2510 	s_sourceAccessMutex.unlock();
2511 	if (tmp) {
2512 	    tmp->clear();
2513 	    TelEngine::destruct(tmp);
2514 	}
2515     }
2516     if (release) {
2517 	SignallingCircuit::destroyed();
2518 	return;
2519     }
2520     status(stat);
2521     m_specialMode.clear();
2522     m_sourceBuffer.clear();
2523     m_consBuffer.clear();
2524     m_consErrors = m_consErrorBytes = m_consTotal = 0;
2525     // Reset echo canceller and tone detector
2526     if (m_device.valid() && (m_crtEchoCancel != m_echoCancel))
2527 	m_device.setEchoCancel(m_echoCancel,m_echoTaps);
2528     m_crtEchoCancel = m_echoCancel;
2529     if (m_device.valid() && (m_crtDtmfDetect != m_dtmfDetect))
2530 	m_device.setDtmfDetect(m_dtmfDetect);
2531     m_crtDtmfDetect = m_dtmfDetect;
2532 }
2533 
2534 // Update format, echo canceller, dtmf detection
setFormat(ZapDevice::Format format)2535 bool ZapCircuit::setFormat(ZapDevice::Format format)
2536 {
2537     m_device.flushBuffers();
2538     if (!m_device.setFormat(format))
2539 	return false;
2540     if (m_crtEchoCancel)
2541 	m_crtEchoCancel = m_device.setEchoCancel(m_crtEchoCancel,m_echoTaps);
2542     if (m_crtDtmfDetect)
2543 	m_crtDtmfDetect = m_device.setDtmfDetect(true);
2544     else
2545 	m_device.setDtmfDetect(false);
2546     return true;
2547 }
2548 
2549 // Get events
checkEvents()2550 void ZapCircuit::checkEvents()
2551 {
2552     char c = 0;
2553     int event = m_device.getEvent(c);
2554     if (!event)
2555 	return;
2556     switch (event) {
2557 	case ZapDevice::DtmfDown:
2558 	case ZapDevice::DtmfUp:
2559 	    if (!m_crtDtmfDetect) {
2560 		DDebug(group(),DebugAll,"ZapCircuit(%u). Ignoring DTMF '%s'=%c [%p]",
2561 		    code(),lookup(event,s_events,""),c,this);
2562 		return;
2563 	    }
2564 	    if (event == ZapDevice::DtmfUp)
2565 		enqueueDigit(true,c);
2566 	    else
2567 		DDebug(group(),DebugAll,"ZapCircuit(%u). Ignoring '%s'=%c [%p]",
2568 		    code(),lookup(event,s_events,""),c,this);
2569 	    return;
2570 	case ZapDevice::Alarm:
2571 	case ZapDevice::NoAlarm:
2572 	    if (event == ZapDevice::Alarm) {
2573 		if (!m_device.checkAlarms())
2574 		    return;
2575 		SignallingCircuitEvent* e = new SignallingCircuitEvent(this,
2576 		    SignallingCircuitEvent::Alarm,lookup(event,s_events));
2577 		e->addParam("alarms",m_device.alarmsText());
2578 		enqueueEvent(e);
2579 	    }
2580 	    else {
2581 		m_device.resetAlarms();
2582 		enqueueEvent(event,SignallingCircuitEvent::NoAlarm);
2583 	    }
2584 	    return;
2585 	default: ;
2586     }
2587     if (processEvent(event,c))
2588 	return;
2589     enqueueEvent(event,SignallingCircuitEvent::Unknown);
2590 }
2591 
2592 // Create source buffer and data source and consumer
createData()2593 void ZapCircuit::createData()
2594 {
2595     m_sourceBuffer.assign(0,m_buflen);
2596     const char* format = lookup(m_format,s_formats,"alaw");
2597     m_source = new ZapSource(this,format);
2598     if (m_canSend)
2599 	m_consumer = new ZapConsumer(this,format);
2600 }
2601 
2602 // Enqueue received events
enqueueEvent(SignallingCircuitEvent * e)2603 inline bool ZapCircuit::enqueueEvent(SignallingCircuitEvent* e)
2604 {
2605     if (e) {
2606 	addEvent(e);
2607 	DDebug(group(),e->type()!=SignallingCircuitEvent::Unknown?DebugAll:DebugStub,
2608 	    "ZapCircuit(%u). Enqueued event '%s' [%p]",code(),e->c_str(),this);
2609     }
2610     return true;
2611 }
2612 
2613 // Enqueue received events
enqueueEvent(int event,SignallingCircuitEvent::Type type)2614 inline bool ZapCircuit::enqueueEvent(int event, SignallingCircuitEvent::Type type)
2615 {
2616     return enqueueEvent(new SignallingCircuitEvent(this,type,lookup(event,s_events)));
2617 }
2618 
2619 // Enqueue received digits
enqueueDigit(bool tone,char digit)2620 bool ZapCircuit::enqueueDigit(bool tone, char digit)
2621 {
2622     char digits[2] = {digit,0};
2623     SignallingCircuitEvent* e = 0;
2624 
2625     if (tone) {
2626 	e = new SignallingCircuitEvent(this,SignallingCircuitEvent::Dtmf,
2627 	    lookup(ZapDevice::DtmfUp,s_events));
2628 	e->addParam("tone",digits);
2629     }
2630     else {
2631 	e = new SignallingCircuitEvent(this,SignallingCircuitEvent::PulseDigit,
2632 	    lookup(ZapDevice::PulseDigit,s_events));
2633 	e->addParam("pulse",digits);
2634     }
2635     return enqueueEvent(e);
2636 }
2637 
2638 
2639 /**
2640  * ZapAnalogCircuit
2641  */
2642 // Change circuit status. Clear events on status change
2643 // New status is Reserved: Open device and start worker if old status is not Connected
2644 // New status is Connect: Create source/consumer
2645 // Cleanup on disconnect
status(Status newStat,bool sync)2646 bool ZapAnalogCircuit::status(Status newStat, bool sync)
2647 {
2648     if (SignallingCircuit::status() == newStat)
2649 	return true;
2650     if (SignallingCircuit::status() == Missing) {
2651 	Debug(group(),DebugNote,
2652 	    "ZapCircuit(%u). Can't change status to '%u'. Circuit is missing [%p]",
2653 	    code(),newStat,this);
2654 	return false;
2655     }
2656     TempObjectCounter cnt(plugin.objectsCounter());
2657     // Allow status change for the following values
2658     switch (newStat) {
2659 	case Missing:
2660 	case Disabled:
2661 	case Idle:
2662 	case Reserved:
2663 	case Special:
2664 	case Connected:
2665 	    break;
2666 	default: ;
2667 	    Debug(group(),DebugStub,
2668 		"ZapCircuit(%u). Can't change status to unhandled value %u [%p]",
2669 		code(),newStat,this);
2670 	    return false;
2671     }
2672 
2673     Status oldStat = SignallingCircuit::status();
2674     if (!SignallingCircuit::status(newStat,sync))
2675 	return false;
2676     clearEvents();
2677     if (!Engine::exiting())
2678 	DDebug(group(),DebugAll,"ZapCircuit(%u). Changed status to %u [%p]",
2679 	    code(),newStat,this);
2680 
2681     if (newStat < Special && m_device.valid())
2682 	m_device.flushBuffers();
2683 
2684     if (newStat == Reserved) {
2685 	// Just cleanup if old status was Connected or the device is already valid
2686 	// Otherwise: open device and start worker
2687 	if (oldStat == Connected || m_device.valid())
2688 	    cleanup(false,Reserved,false);
2689 	else {
2690 	    String addr;
2691 	    if (group())
2692 		addr << group()->debugName() << "/";
2693 	    addr << code();
2694 	    if (m_device.open(0,m_buflen) && ZapWorkerClient::start(m_priority,group(),addr))
2695 		setFormat(m_format);
2696 	    else
2697 		cleanup(false,Idle,true);
2698 	}
2699 	return SignallingCircuit::status() == Reserved;
2700     }
2701     else if (newStat >= Special) {
2702 	if (m_device.valid()) {
2703 	    createData();
2704 	    if (newStat == Special) {
2705 		Message m("circuit.special");
2706 		m.userData(this);
2707 		if (group())
2708 		    m.addParam("group",group()->toString());
2709 		if (span())
2710 		    m.addParam("span",span()->toString());
2711 		if (m_specialMode)
2712 		    m.addParam("mode",m_specialMode);
2713 		if (!Engine::dispatch(m))
2714 		    cleanup(false,Idle,true);
2715 	    }
2716 	}
2717 	else
2718 	    cleanup(false,Idle,true);
2719 	return SignallingCircuit::status() == newStat;
2720     }
2721     return true;
2722 }
2723 
2724 // Get circuit data
getParam(const String & param,String & value) const2725 bool ZapAnalogCircuit::getParam(const String& param, String& value) const
2726 {
2727     if (param == "hook") {
2728 	value = String::boolText(m_hook);
2729 	return true;
2730     }
2731     return ZapCircuit::getParam(param,value);
2732 }
2733 
2734 // Set line polarity
setParam(const String & param,const String & value)2735 bool ZapAnalogCircuit::setParam(const String& param, const String& value)
2736 {
2737     TempObjectCounter cnt(plugin.objectsCounter());
2738     if (param == "polarity") {
2739 	if (!(m_device.valid() && value.isBoolean()))
2740 	    return false;
2741 	int state = value.toBoolean() ? 1 : 0;
2742 	return m_device.setPolarity(state,DebugNote);
2743     }
2744     return ZapCircuit::setParam(param,value);
2745 }
2746 
2747 // Send an event
sendEvent(SignallingCircuitEvent::Type type,NamedList * params)2748 bool ZapAnalogCircuit::sendEvent(SignallingCircuitEvent::Type type, NamedList* params)
2749 {
2750     if (!m_canSend)
2751 	return false;
2752 
2753     if (type == SignallingCircuitEvent::Dtmf)
2754 	return ZapCircuit::sendEvent(type,params);
2755 
2756     TempObjectCounter cnt(plugin.objectsCounter());
2757     XDebug(group(),DebugAll,"ZapAnalogCircuit(%u). sendEvent(%u) [%p]",code(),type,this);
2758     switch (type) {
2759 	case SignallingCircuitEvent::OnHook:
2760 	    if (!m_device.sendHook(ZapDevice::HookOn))
2761 		return false;
2762 	    changeHook(true);
2763 	    return true;
2764 	case SignallingCircuitEvent::OffHook:
2765 	    if (!m_device.sendHook(ZapDevice::HookOff))
2766 		return false;
2767 	    changeHook(false);
2768 	    return true;
2769 	case SignallingCircuitEvent::Polarity:
2770 	    if (!params)
2771 		return false;
2772 	    return setParam("polarity",params->getValue("polarity"));
2773 	case SignallingCircuitEvent::Wink:
2774 	    return m_device.sendHook(ZapDevice::HookWink);
2775 	case SignallingCircuitEvent::Flash:
2776 	    return m_device.sendHook(ZapDevice::HookFlash);
2777 	case SignallingCircuitEvent::RingBegin:
2778 	    return m_device.sendHook(ZapDevice::HookRing);
2779 	case SignallingCircuitEvent::RingEnd:
2780 	    return m_device.sendHook(ZapDevice::HookRingOff);
2781 	case SignallingCircuitEvent::StartLine:
2782 	    return m_device.sendHook(ZapDevice::HookStart);
2783 	default: ;
2784     }
2785     return ZapCircuit::sendEvent(type,params);
2786 }
2787 
2788 // Process additional events. Return false if not processed
processEvent(int event,char c)2789 bool ZapAnalogCircuit::processEvent(int event, char c)
2790 {
2791     switch (event) {
2792 	case ZapDevice::RingerOn:
2793 	    return enqueueEvent(event,SignallingCircuitEvent::RingerOn);
2794 	case ZapDevice::RingerOff:
2795 	    return enqueueEvent(event,SignallingCircuitEvent::RingerOff);
2796 #ifdef DAHDI_EVENT_REMOVED
2797 	case ZapDevice::Removed:
2798 #endif
2799 	case ZapDevice::OnHook:
2800 	    changeHook(true);
2801 	    return enqueueEvent(event,SignallingCircuitEvent::OnHook);
2802 	case ZapDevice::RingBegin:
2803 	    m_device.setLinear(0,DebugAll);
2804 	    return enqueueEvent(event,SignallingCircuitEvent::RingBegin);
2805 	case ZapDevice::OffHookRing:
2806 	    if (m_device.type() == ZapDevice::FXS) {
2807 		changeHook(false);
2808 		return enqueueEvent(event,SignallingCircuitEvent::OffHook);
2809 	    }
2810 	    return enqueueEvent(event,SignallingCircuitEvent::RingerOff);
2811 	case ZapDevice::Polarity:
2812 	    return enqueueEvent(event,SignallingCircuitEvent::Polarity);
2813 	case ZapDevice::WinkFlash:
2814 	    if (m_hook)
2815 		return enqueueEvent(event,SignallingCircuitEvent::Wink);
2816 	    return enqueueEvent(event,SignallingCircuitEvent::Flash);
2817 	case ZapDevice::HookComplete:
2818 	    return enqueueEvent(event,SignallingCircuitEvent::LineStarted);
2819 	case ZapDevice::DialComplete:
2820 	    return enqueueEvent(event,SignallingCircuitEvent::DialComplete);
2821 	case ZapDevice::PulseDigit:
2822 	    return enqueueDigit(false,c);
2823 	case ZapDevice::PulseStart:
2824 	    return enqueueEvent(event,SignallingCircuitEvent::PulseStart);
2825 	case ZapDevice::Timeout:
2826 	    return enqueueEvent(event,SignallingCircuitEvent::Timeout);
2827 	case ZapDevice::BitsChanged:
2828 	case ZapDevice::TimerPing:
2829 	    DDebug(group(),DebugStub,"ZapCircuit(%u). Unhandled event %u [%p]",
2830 		code(),event,this);
2831 	    break;
2832 	default:
2833 	    Debug(group(),DebugStub,"ZapCircuit(%u). Unknown event %u [%p]",
2834 		code(),event,this);
2835     }
2836     return false;
2837 }
2838 
2839 // Process incoming data
process()2840 bool ZapAnalogCircuit::process()
2841 {
2842     if (!(m_device.valid() && SignallingCircuit::status() != SignallingCircuit::Disabled))
2843 	return false;
2844 
2845     m_device.pollHook();
2846     checkEvents();
2847 
2848     s_sourceAccessMutex.lock();
2849     RefPointer<ZapSource> src = m_source;
2850     s_sourceAccessMutex.unlock();
2851 
2852     if (!(src && m_device.select(10) && m_device.canRead()))
2853 	return false;
2854 
2855     int r = m_device.recv(m_sourceBuffer.data(),m_sourceBuffer.length());
2856     if (m_device.event())
2857 	checkEvents();
2858     if (r > 0) {
2859 	if ((unsigned int)r != m_sourceBuffer.length())
2860 	    ::memset((unsigned char*)m_sourceBuffer.data() + r,m_idleValue,m_sourceBuffer.length() - r);
2861 	XDebug(group(),DebugAll,"ZapCircuit(%u). Forwarding %u bytes [%p]",
2862 	    code(),m_sourceBuffer.length(),this);
2863 	src->Forward(m_sourceBuffer);
2864 	return true;
2865     }
2866 
2867     return false;
2868 }
2869 
2870 // Change hook state if different
changeHook(bool hook)2871 void ZapAnalogCircuit::changeHook(bool hook)
2872 {
2873     if (m_hook == hook)
2874 	return;
2875     DDebug(group(),DebugInfo,"ZapCircuit(%u). Hook state changed to %s [%p]",
2876 	code(),hook?"ON":"OFF",this);
2877     m_hook = hook;
2878 }
2879 
2880 
2881 /**
2882  * ZapSource
2883  */
setAddr(String & addr,ZapCircuit * cic)2884 inline void setAddr(String& addr, ZapCircuit* cic)
2885 {
2886 #ifdef XDEBUG
2887     if (cic) {
2888 	if (cic->group())
2889 	    addr << cic->group()->debugName() << "/";
2890 	addr << cic->code();
2891     }
2892     else
2893 	addr = -1;
2894 #endif
2895 }
2896 
ZapSource(ZapCircuit * circuit,const char * format)2897 ZapSource::ZapSource(ZapCircuit* circuit, const char* format)
2898     : DataSource(format)
2899 {
2900     setAddr(m_address,circuit);
2901     XDebug(&plugin,DebugAll,"ZapSource::ZapSource() cic=%s [%p]",m_address.c_str(),this);
2902 }
2903 
~ZapSource()2904 ZapSource::~ZapSource()
2905 {
2906     XDebug(&plugin,DebugAll,"ZapSource::~ZapSource() cic=%s [%p]",m_address.c_str(),this);
2907 }
2908 
2909 
2910 /**
2911  * ZapConsumer
2912  */
ZapConsumer(ZapCircuit * circuit,const char * format)2913 ZapConsumer::ZapConsumer(ZapCircuit* circuit, const char* format)
2914     : DataConsumer(format),
2915     m_circuit(circuit)
2916 {
2917     setAddr(m_address,circuit);
2918     XDebug(&plugin,DebugAll,"ZapConsumer::ZapConsumer() cic=%s [%p]",m_address.c_str(),this);
2919 }
2920 
~ZapConsumer()2921 ZapConsumer::~ZapConsumer()
2922 {
2923     XDebug(&plugin,DebugAll,"ZapConsumer::~ZapConsumer() cic=%s [%p]",m_address.c_str(),this);
2924 }
2925 
2926 
2927 /**
2928  * ZapModule
2929  */
2930 String ZapModule::s_statusCmd[StatusCmdCount] = {"spans","channels","all"};
2931 
ZapModule()2932 ZapModule::ZapModule()
2933     : Module("zaptel","misc",true),
2934     m_init(false),
2935     m_count(0),
2936     m_active(0)
2937 {
2938     Output("Loaded module Zaptel");
2939     m_prefix << name() << "/";
2940     m_statusCmd << "status " << name();
2941 }
2942 
~ZapModule()2943 ZapModule::~ZapModule()
2944 {
2945     Output("Unloading module Zaptel");
2946 }
2947 
append(ZapDevice * dev)2948 void ZapModule::append(ZapDevice* dev)
2949 {
2950     if (!dev)
2951 	return;
2952     Lock lock(this);
2953     m_devices.append(dev)->setDelete(false);
2954     m_count = m_devices.count();
2955 }
2956 
remove(ZapDevice * dev)2957 void ZapModule::remove(ZapDevice* dev)
2958 {
2959     if (!dev)
2960 	return;
2961     Lock lock(this);
2962     m_devices.remove(dev,false);
2963     m_count = m_devices.count();
2964 }
2965 
initialize()2966 void ZapModule::initialize()
2967 {
2968     Output("Initializing module Zaptel");
2969 
2970     Configuration cfg(Engine::configFile("zapcard"));
2971     cfg.load();
2972 
2973     NamedList dummy("");
2974     NamedList* general = cfg.getSection("general");
2975     if (!general)
2976 	general = &dummy;
2977 
2978     ZapDevice dev(0,false,true);
2979     if (!dev.valid())
2980 	Debug(this,DebugNote,"Failed to open zaptel device: driver might not be loaded");
2981 
2982     int dtmfLen = 0;
2983     if (!m_init) {
2984 	m_init = true;
2985 	setup();
2986 	installRelay(Command);
2987 	// Set DTMF/MF length
2988 	if (dev.valid() && dev.dialParams(false,dtmfLen,dtmfLen)) {
2989 	    dtmfLen = general->getIntValue("tonelength",dtmfLen);
2990 	    dev.dialParams(true,dtmfLen,dtmfLen);
2991 	}
2992     }
2993     if (dev.valid() && debugAt(DebugAll)) {
2994 	NamedList nl("");
2995 	dev.getVersion(nl);
2996 	dtmfLen = 0;
2997 	dev.dialParams(false,dtmfLen,dtmfLen);
2998 	Debug(this,DebugAll,"version=%s echocanceller=%s tonelength=%d samples",
2999 	    nl.getValue("version"),nl.getValue("echocanceller"),dtmfLen);
3000     }
3001 }
3002 
3003 
3004 // Find a device by its Zaptel channel
findZaptelChan(int chan)3005 ZapDevice* ZapModule::findZaptelChan(int chan)
3006 {
3007     Lock lock(this);
3008     for (ObjList* o = m_devices.skipNull(); o; o = o->skipNext()) {
3009 	ZapDevice* dev = static_cast<ZapDevice*>(o->get());
3010 	if ((int)dev->channel() == chan)
3011 	    return dev;
3012     }
3013     return 0;
3014 }
3015 
received(Message & msg,int id)3016 bool ZapModule::received(Message& msg, int id)
3017 {
3018     if (id == Status) {
3019 	String dest = msg.getValue("module");
3020 
3021 	// Module status
3022 	if (!dest || dest == name()) {
3023 	    Module::msgStatus(msg);
3024 	    return false;
3025 	}
3026 
3027 	Lock lock(this);
3028 
3029 	// Device status
3030 	if (dest.startSkip(prefix(),false)) {
3031 	    ZapDevice* dev = findZaptelChan((unsigned int)dest.toInteger());
3032 	    if (!dev)
3033 		return false;
3034 	    msg.retValue().clear();
3035 	    msg.retValue() << "name=" << dev->zapName();
3036 	    msg.retValue() << ",module=" << name();
3037 	    msg.retValue() << ",type=" << lookup(dev->type(),s_types);
3038 	    if (dev->span() != -1) {
3039 		msg.retValue() << ",zapteltype=" << lookup(dev->zapsig(),s_zaptelSig);
3040 		msg.retValue() << ",span=" << dev->span();
3041 		msg.retValue() << ",spanpos=" << dev->spanPos();
3042 		msg.retValue() << ",alarms=" << dev->alarmsText();
3043 	    }
3044 	    else
3045 		msg.retValue() << ",zapteltype=not-configured,span=,spanpos=,alarms=";
3046 	    msg.retValue() << ",address=" << dev->address();
3047 	    msg.retValue() << "\r\n";
3048 	    return true;
3049 	}
3050 
3051 	// Additional commands
3052 	if (dest.startSkip(name(),false)) {
3053 	    dest.trimBlanks();
3054 	    int cmd = 0;
3055 	    for (; cmd < StatusCmdCount; cmd++)
3056 		if (s_statusCmd[cmd] == dest)
3057 		    break;
3058 	    if (cmd == ZapSpans) {
3059 		ZapDevice* ctl = new ZapDevice(0);
3060 		NamedList ver("");
3061 		ctl->getVersion(ver);
3062 		msg.retValue().clear();
3063 		msg.retValue() << "module=" << name() << "," << s_spanParamsHdr;
3064 		msg.retValue() << ";version=" << ver.getValue("version");
3065 		msg.retValue() << ",echocanceller=" << ver.getValue("echocanceller");
3066 		for (int span = 1; true; span++) {
3067 		    NamedList p("");
3068 		    int total = 0;
3069 		    bool ok = ctl->getSpanInfo(span,p,&total);
3070 		    if (span == 1)
3071 			msg.retValue() << ",count=" << total;
3072 		    if (!ok)
3073 			break;
3074 		    // format=Channels|Total|Alarms|Name|Description
3075 		    msg.retValue() << ";" << span << "=" << p.getValue("configured-chans");
3076 		    msg.retValue() << "|" << p.getValue("total-chans");
3077 		    msg.retValue() << "|" << p.getValue("alarmstext");
3078 		    msg.retValue() << "|" << p.getValue("name");
3079 		    msg.retValue() << "|" << p.getValue("desc");
3080 		}
3081 		TelEngine::destruct(ctl);
3082 	    }
3083 	    else if (cmd == ZapChannels || cmd == ZapChannelsAll) {
3084 		ZapDevice* ctl = new ZapDevice(0);
3085 		String s;
3086 		unsigned int chan = 0;
3087 		for (int span = 1; ctl->valid(); span++) {
3088 		    // Check span
3089 		    NamedList p("");
3090 		    if (!ctl->getSpanInfo(span,p))
3091 			break;
3092 
3093 		    // Get info
3094 		    int chans = p.getIntValue("total-chans");
3095 		    for (int i = 0; i < chans; i++) {
3096 			chan++;
3097 			// Get device
3098 			// Create or reset debuger to avoid unwanted debug output to console
3099 			bool created = false;
3100 			bool opened = false;
3101 			ZapDevice* dev = findZaptelChan(chan);
3102 			if (!dev) {
3103 			    dev = new ZapDevice(chan);
3104 			    created = true;
3105 			}
3106 			else if (dev->owner())
3107 			    dev->owner()->debugEnabled(false);
3108 			if (!dev->valid()) {
3109 			    dev->open(0,0);
3110 			    opened = true;
3111 			}
3112 
3113 			bool show = (dev->span() == span) || (cmd == ZapChannelsAll);
3114 			if (show) {
3115 			    // format=Type|ZaptelType|Span|SpanPos|Alarms|Address
3116 			    s << ";" << dev->channel() << "=" << lookup(dev->type(),s_types);
3117 			    if (dev->span() == span) {
3118 				s << "|" << lookup(dev->zapsig(),s_zaptelSig);
3119 				s << "|" << dev->span();
3120 				s << "|" << dev->spanPos();
3121 				s << "|" << dev->alarmsText();
3122 			    }
3123 			    else
3124 				s << "|not-configured|||";
3125 			    s << "|" << dev->address();
3126 			}
3127 
3128 			// Cleanup if we opened/created the device
3129 			if (created) {
3130 			    TelEngine::destruct(dev);
3131 			    continue;
3132 			}
3133 			if (opened)
3134 			    dev->close();
3135 			if (dev->owner())
3136 			    dev->owner()->debugEnabled(true);
3137 		    }
3138 		}
3139 		TelEngine::destruct(ctl);
3140 
3141 		msg.retValue().clear();
3142 		msg.retValue() << "module=" << name() << "," << s_chanParamsHdr;
3143 		msg.retValue() << ";used=" << m_count << ",total=" << chan;
3144 		msg.retValue() << s;
3145 	    }
3146 	    else
3147 		return false;
3148 	    msg.retValue() << "\r\n";
3149 	    return true;
3150 	}
3151 
3152 	return false;
3153     }
3154     return Module::received(msg,id);
3155 }
3156 
statusModule(String & str)3157 void ZapModule::statusModule(String& str)
3158 {
3159     Module::statusModule(str);
3160     str.append(s_chanParamsHdr,",");
3161 }
3162 
statusParams(String & str)3163 void ZapModule::statusParams(String& str)
3164 {
3165     Module::statusParams(str);
3166     str.append("active=",",") << m_active;
3167     str << ",count=" << m_count;
3168 }
3169 
statusDetail(String & str)3170 void ZapModule::statusDetail(String& str)
3171 {
3172     // format=Type|ZaptelType|Span|SpanPos|Alarms|Address
3173     for (ObjList* o = m_devices.skipNull(); o; o = o->skipNext()) {
3174 	ZapDevice* dev = static_cast<ZapDevice*>(o->get());
3175 	str.append(String(dev->channel()),";") << "=" << lookup(dev->type(),s_types);
3176 	str << "|" << lookup(dev->zapsig(),s_zaptelSig);
3177 	str << "|" << dev->span();
3178 	str << "|" << dev->spanPos();
3179 	str << "|" << dev->alarmsText();
3180 	str << "|" << dev->address();
3181     }
3182 }
3183 
commandComplete(Message & msg,const String & partLine,const String & partWord)3184 bool ZapModule::commandComplete(Message& msg, const String& partLine,
3185 	const String& partWord)
3186 {
3187     bool ok = Module::commandComplete(msg,partLine,partWord);
3188     if (!partLine.startsWith("status"))
3189 	return ok;
3190     Lock lock(this);
3191     if (name().startsWith(partWord)) {
3192 	if (m_devices.skipNull())
3193 	    msg.retValue().append(prefix(),"\t");
3194 	return ok;
3195     }
3196     if (partLine == m_statusCmd) {
3197 	for (unsigned int i = 0; i < StatusCmdCount; i++)
3198 	    itemComplete(msg.retValue(),s_statusCmd[i],partWord);
3199 	return true;
3200     }
3201     if (partWord.startsWith(prefix())) {
3202 	for (ObjList* o = m_devices.skipNull(); o; o = o->skipNext())
3203 	    itemComplete(msg.retValue(),static_cast<ZapDevice*>(o->get())->zapName(),partWord);
3204 	return true;
3205     }
3206     return ok;
3207 }
3208 
3209 }; // anonymous namespace
3210 
3211 #endif /* _WINDOWS */
3212 
3213 /* vi: set ts=8 sw=4 sts=4 noet: */
3214