1 /**
2  * yateradio.h
3  * Radio library
4  * This file is part of the YATE Project http://YATE.null.ro
5  *
6  * Yet Another Telephony Engine - a fully featured software PBX and IVR
7  * Copyright (C) 2011-2014 Null Team
8  * Copyright (C) 2015 LEGBA Inc
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 #ifndef __YATERADIO_H
23 #define __YATERADIO_H
24 
25 #include <yateclass.h>
26 #include <yatexml.h>
27 
28 #ifdef _WINDOWS
29 
30 #ifdef LIBYRADIO_EXPORTS
31 #define YRADIO_API __declspec(dllexport)
32 #else
33 #ifndef LIBYRADIO_STATIC
34 #define YRADIO_API __declspec(dllimport)
35 #endif
36 #endif
37 
38 #endif /* _WINDOWS */
39 
40 #ifndef YRADIO_API
41 #define YRADIO_API
42 #endif
43 
44 
45 namespace TelEngine {
46 
47 class GSML3Codec;                        // GSM Layer codec
48 class RadioCapability;                   // Radio device capabilities
49 class RadioInterface;                    // Generic radio interface
50 
51 class YRADIO_API GSML3Codec
52 {
53     YNOCOPY(GSML3Codec);
54 public:
55     /**
56      * Codec flags
57      */
58     enum Flags {
59 	XmlDumpMsg = 0x01,
60 	XmlDumpIEs = 0x02,
61 	MSCoder    = 0x04,
62     };
63 
64     /**
65      * Codec return status
66      */
67     enum Status {
68 	NoError = 0,
69 	MsgTooShort,
70 	UnknownProto,
71 	ParserErr,
72 	MissingParam,
73 	IncorrectOptionalIE,
74 	IncorrectMandatoryIE,
75 	MissingMandatoryIE,
76 	UnknownMsgType,
77     };
78 
79     /**
80      * Protocol discriminator according to ETSI TS 124 007 V11.0.0, section 11.2.3.1.1
81      */
82     enum Protocol {
83 	GCC       = 0x00, // Group Call Control
84 	BCC       = 0x01, // Broadcast Call Control
85 	EPS_SM    = 0x02, // EPS Session Management
86 	CC        = 0x03, // Call Control; Call Related SS messages
87 	GTTP      = 0x04, // GPRS Transparent Transport Protocol (GTTP)
88 	MM        = 0x05, // Mobility Management
89 	RRM       = 0x06, // Radio Resources Management
90 	EPS_MM    = 0x07, // EPS Mobility Management
91 	GPRS_MM   = 0x08, // GPRS Mobility Management
92 	SMS       = 0x09, // SMS
93 	GPRS_SM   = 0x0a, // GPRS Session Management
94 	SS        = 0x0b, // Non Call Related SS messages
95 	LCS       = 0x0c, // Location services
96 	Extension = 0x0e, // reserved for extension of the PD to one octet length
97 	Test      = 0x0f, // used by tests procedures described in 3GPP TS 44.014, 3GPP TS 34.109 and 3GPP TS 36.509
98 	Unknown   = 0xff,
99     };
100 
101     /**
102      * IE types
103      */
104     enum Type {
105 	NoType = 0,
106 	T,
107 	V,
108 	TV,
109 	LV,
110 	TLV,
111 	LVE,
112 	TLVE,
113     };
114 
115     /**
116      * Type of XML data to generate
117      */
118     enum XmlType {
119 	Skip,
120 	XmlElem,
121 	XmlRoot,
122     };
123 
124     /**
125      * EPS Security Headers
126      */
127     enum EPSSecurityHeader {
128 	PlainNAS                           = 0x00,
129 	IntegrityProtect                   = 0x01,
130 	IntegrityProtectCiphered           = 0x02,
131 	IntegrityProtectNewEPSCtxt         = 0x03,
132 	IntegrityProtectCipheredNewEPSCtxt = 0x04,
133 	ServiceRequestHeader               = 0xa0,
134     };
135 
136     /**
137      * Constructor
138      */
139     GSML3Codec(DebugEnabler* dbg = 0);
140 
141     /**
142      * Decode layer 3 message payload
143      * @param in Input buffer containing the data to be decoded
144      * @param len Length of input buffer
145      * @param out XmlElement into which the decoded data is returned
146      * @param params Encoder parameters
147      * @return Parsing result: 0 (NoError) if succeeded, error status otherwise
148      */
149     unsigned int decode(const uint8_t* in, unsigned int len, XmlElement*& out, const NamedList& params = NamedList::empty());
150 
151     /**
152      * Encode a layer 3 message
153      * @param in Layer 3 message in XML form
154      * @param out Output buffer into which to put encoded data
155      * @param params Encoder parameters
156      * @return Parsing result: 0 (NoError) if succeeded, error status otherwise
157      */
158     unsigned int encode(const XmlElement* in, DataBlock& out, const NamedList& params = NamedList::empty());
159 
160     /**
161      * Decode layer 3 message from an existing XML
162      * @param xml XML which contains layer 3 messages to decode and into which the decoded XML will be put
163      * @param params Decoder parameters
164      * @return Parsing result: 0 (NoError) if succeeded, error status otherwise
165      */
166     unsigned int decode(XmlElement* xml, const NamedList& params = NamedList::empty());
167 
168     /**
169      * Encode a layer 3 message from an existing XML
170      * @param xml XML which contains a layer 3 message in XML form. The message will be replaced with its encoded buffer
171      * @param params Encoder parameters
172      * @return Parsing result: 0 (NoError) if succeeded, error status otherwise
173      */
174     unsigned int encode(XmlElement* xml, const NamedList& params = NamedList::empty());
175 
176     /**
177      * Set data used in debug
178      * @param enabler The DebugEnabler to use (0 to to use the engine)
179      * @param ptr Pointer to print, 0 to use the codec pointer
180      */
181     void setCodecDebug(DebugEnabler* enabler = 0, void* ptr = 0);
182 
183     /**
184      * Retrieve codec flags
185      * @return Codec flags
186      */
flags()187     inline uint8_t flags() const
188 	{ return m_flags; }
189 
190     /**
191      * Set codec flags
192      * @param flgs Flags to set
193      * @param reset Reset flags before setting these ones
194      */
195     inline void setFlags(uint8_t flgs, bool reset = false)
196     {
197 	if (reset)
198 	    resetFlags();
199 	m_flags |= flgs;
200     }
201 
202     /**
203      * Reset codec flags
204      * @param flgs Flags to reset. If 0, all flags are reset
205      */
206     inline void resetFlags(uint8_t flgs = 0)
207     {
208 	if (flgs)
209 	    m_flags &= ~flgs;
210 	else
211 	    m_flags = 0;
212     }
213 
214     /**
215      * Activate printing of debug messages
216      * @param on True to activate, false to disable
217      */
218     inline void setPrintDbg(bool on = false)
219 	{ m_printDbg = on; }
220 
221     /**
222      * Get printing of debug messages flag
223      * @return True if debugging is activated, false otherwise
224      */
printDbg()225     inline bool printDbg() const
226 	{ return m_printDbg; }
227 
228     /**
229      * Get DebugEnabler used by this codec
230      * @return DebugEnabler used by the codec
231      */
dbg()232     inline DebugEnabler* dbg() const
233 	{ return m_dbg; }
234 
235     /**
236      * Retrieve the codec pointer used for debug messages
237      * @return Codec pointer used for debug messages
238      */
ptr()239     inline void* ptr() const
240 	{ return m_ptr; }
241 
242     /**
243      * Decode GSM 7bit buffer
244      * @param buf Input buffer
245      * @param len Input buffer length
246      * @param text Destination text
247      * @param heptets Maximum number of heptets in buffer
248      */
249     static void decodeGSM7Bit(unsigned char* buf, unsigned int len, String& text,
250 	unsigned int heptets = (unsigned int)-1);
251 
252     /**
253      * Encode GSM 7bit buffer
254      * @param text Input text
255      * @param buf Destination buffer
256      * @return True if all characters were encoded correctly
257      */
258     static bool encodeGSM7Bit(const String& text, DataBlock& buf);
259 
260     /**
261      * IE types dictionary
262      */
263     static const TokenDict s_typeDict[];
264 
265     /**
266      * L3 Protocols dictionary
267      */
268     static const TokenDict s_protoDict[];
269 
270     /**
271      * EPS Security Headers dictionary
272      */
273     static const TokenDict s_securityHeaders[];
274 
275     /**
276      * Errors dictionary
277      */
278     static const TokenDict s_errorsDict[];
279 
280     /**
281      * Mobility Management reject causes dictionary
282      */
283     static const TokenDict s_mmRejectCause[];
284 
285     /**
286      * GPRS Mobility Management reject causes dictionary
287      */
288     static const TokenDict s_gmmRejectCause[];
289 
290 private:
291 
292     unsigned int decodeXml(XmlElement* xml, const NamedList& params, const String& pduTag);
293     unsigned int encodeXml(XmlElement* xml, const NamedList& params, const String& pduTag);
294     void printDbg(int dbgLevel, const uint8_t* in, unsigned int len, XmlElement* xml, bool encode = false);
295 
296     uint8_t m_flags;                 // Codec flags
297     // data used for debugging messages
298     DebugEnabler* m_dbg;
299     void* m_ptr;
300     // activate debug
301     bool m_printDbg;
302 };
303 
304 
305 /**
306  * @short Radio device capabilities
307  * Radio capability object describes the parameter ranges of the radio handware.
308  */
309 class YRADIO_API RadioCapability
310 {
311 public:
312     /**
313      * Constructor
314      */
315     RadioCapability();
316 
317     unsigned maxPorts;                   // Available number of ports
318     unsigned currPorts;                  // Number of used (available) ports
319     uint64_t maxTuneFreq;                // Maximum allowed tuning frequency (in Hz)
320     uint64_t minTuneFreq;                // Minimum allowed tuning frequency (in Hz)
321     unsigned maxSampleRate;              // Maximum allowed sampling rate (in Hz)
322     unsigned minSampleRate;              // Minimum allowed sampling rate (in Hz)
323     unsigned maxFilterBandwidth;         // Maximum allowed anti-alias filter bandwidth (in Hz)
324     unsigned minFilterBandwidth;         // Minimum allowed anti-alias filter bandwidth (in Hz)
325     unsigned rxLatency;                  // Estimated radio latency (in samples)
326     unsigned txLatency;                  // Estimated transmit latency (in samples)
327 };
328 
329 
330 /**
331  * Keeps a buffer pointer with offset and valid samples
332  * @short A buffer description
333  */
334 class RadioBufDesc
335 {
336 public:
337     /**
338      * Constructor
339      */
RadioBufDesc()340     inline RadioBufDesc()
341 	: samples(0), offs(0), valid(0)
342 	{}
343 
344     /**
345      * Reset the buffer
346      * @param value Offset and valid samples value
347      */
348     inline void reset(unsigned int value = 0)
349 	{ offs = valid = value; }
350 
351     /**
352      * Reset the buffer
353      * @param offset New offset
354      * @param validS New valid samples value
355      */
reset(unsigned int offset,unsigned int validS)356     inline void reset(unsigned int offset, unsigned int validS) {
357 	    offs = offset;
358 	    valid = validS;
359 	}
360 
361     /**
362      * Check if the buffer is valid
363      * @param minSamples Required minimum number of valid samples
364      * @return True if valid, false otherwise
365      */
validSamples(unsigned int minSamples)366     inline bool validSamples(unsigned int minSamples) const
367 	{ return !minSamples || minSamples >= offs || minSamples >= valid; }
368 
369     float* samples;                      // Current read buffer
370     unsigned int offs;                   // Current buffer offset (in sample periods)
371     unsigned int valid;                  // The number of valid samples in buffer
372 };
373 
374 
375 /**
376  * Keeps buffers used by RadioInterface::read()
377  * @short RadioInterface read buffers
378  */
379 class RadioReadBufs : public GenObject
380 {
381 public:
382     /**
383      * Constructor
384      * @param len Single buffer length (in sample periods)
385      * @param validThres Optional threshold for valid samples. Used when read timestamp
386      *  data is in the future and a portion of the buffer need to be reset.
387      *  If valid samples are below threshold data won't be set or copied
388      */
389     inline RadioReadBufs(unsigned int len = 0, unsigned int validThres = 0)
m_bufSamples(len)390 	: m_bufSamples(len), m_validMin(validThres)
391 	{}
392 
393     /**
394      * Reset buffers
395      * @param len Single buffer length (in sample periods)
396      * @param validThres Optional threshold for valid samples
397      */
reset(unsigned int len,unsigned int validThres)398     inline void reset(unsigned int len, unsigned int validThres) {
399 	    m_bufSamples = len;
400 	    m_validMin = validThres;
401 	    crt.reset();
402 	    aux.reset();
403 	    extra.reset();
404 	}
405 
406     /**
407      * Retrieve the length of a single buffer
408      * @return Buffer length (in sample periods)
409      */
bufSamples()410     inline unsigned int bufSamples() const
411 	{ return m_bufSamples; }
412 
413     /**
414      * Check if a given buffer is full (offset is at least buffer length)
415      * @param buf Buffer to check
416      * @return True if the given buffer is full, false otherwise
417      */
full(RadioBufDesc & buf)418     inline bool full(RadioBufDesc& buf) const
419 	{ return buf.offs >= m_bufSamples; }
420 
421     /**
422      * Check if a given is valid (have enough valid samples)
423      * @param buf Buffer to check
424      * @return True if the given buffer is valid, false otherwise
425      */
valid(RadioBufDesc & buf)426     inline bool valid(RadioBufDesc& buf) const
427 	{ return buf.validSamples(m_validMin); }
428 
429     /**
430      * Dump data for debug purposes
431      * @param buf Destination buffer
432      * @return Destination buffer reference
433      */
434     String& dump(String& buf);
435 
436     RadioBufDesc crt;
437     RadioBufDesc aux;
438     RadioBufDesc extra;
439 
440 protected:
441     unsigned int m_bufSamples;           // Buffers length in sample periods
442     unsigned int m_validMin;             // Valid samples threshold
443 };
444 
445 
446 /**
447  * @short Generic radio interface
448  *
449  * @note Some parameters are quantized by the radio hardware. If the caller requests a parameter
450  * value that cannot be matched exactly, the setting method will set the parameter to the
451  * best avaiable match and return "NotExact". For such parameters, there is a corresponding
452  * readback method to get the actual value used.
453  *
454  * @note If a method does not include a radio port number, then that method applies to all connected ports.
455  *
456  * @note The interface may control multiple radios, with each one appearing as a port. However, in this case,
457  *  - all radios are to be synched on the sample clock
458  *  - all radios are to be of the same hardware type
459  *
460  * @note If the performance of the radio hardware changes, the API indicates this with the RFHardwareChange
461  * flag. If this flag appears in a result code, the application should:
462  *  - read a new RadioCapabilties object
463  *  - revisit all of the application-level parameter settings on the radio
464  *  - check the status() method on each port to identify single-port errors
465  */
466 class YRADIO_API RadioInterface : public RefObject, public DebugEnabler
467 {
468     YCLASS(RadioInterface,RefObject);
469 public:
470     /** Error code bit positions in the error code mask. */
471     enum ErrorCode {
472 	NoError = 0,
473 	Failure = (1 << 1),              // Unknown error
474 	HardwareIOError = (1 << 2),      // Communication error with HW
475 	NotInitialized = (1 << 3),       // Interface not initialized
476 	NotSupported = (1 << 4),         // Feature not supported
477 	NotCalibrated = (1 << 5),        // The radio is not calibrated
478 	TooEarly = (1 << 6),             // Timestamp is in the past
479 	TooLate = (1 << 7),              // Timestamp is in the future
480 	OutOfRange = (1 << 8),           // A requested parameter setting is out of range
481 	NotExact = (1 << 9),             // The affected value is not an exact match to the requested one
482 	DataLost = (1 << 10),            // Received data lost due to slow reads
483 	Saturation = (1 << 11),          // Data contain values outside of +/-1+/-j
484 	RFHardwareFail = (1 << 12),      // Failure in RF hardware
485 	RFHardwareChange = (1 << 13),    // Change in RF hardware, not outright failure
486 	EnvironmentalFault = (1 << 14),  // Environmental spec exceeded for radio HW
487 	InvalidPort = (1 << 15),         // Invalid port number
488 	Pending = (1 << 16),             // Operation is pending
489 	Cancelled = (1 << 17),           // Operation cancelled
490 	Timeout = (1 << 18),             // Operation timeout
491 	HardwareNotAvailable = (1 << 19),// Device not found
492 	InsufficientSpeed = (1 << 20),   // Device has insufficient speed to fulfill required transfer rate
493 	// Masks
494 	// Errors indicating automatic application restart should not be performed
495 	// These may indicate misconfig or hardware failures requiring system restart
496 	NoAutoRestartMask = HardwareNotAvailable | InsufficientSpeed,
497 	// Errors requiring radio or port shutdown
498 	FatalErrorMask = HardwareIOError | RFHardwareFail | EnvironmentalFault | Failure |
499 	    NoAutoRestartMask,
500 	// Errors that can be cleared
501 	ClearErrorMask = TooEarly | TooLate | NotExact | DataLost | Saturation |
502 	    InvalidPort | Timeout,
503 	// Errors that are specific to a single call
504 	LocalErrorMask = NotInitialized | NotCalibrated | TooEarly | TooLate | OutOfRange |
505 	    NotExact | DataLost | Saturation | RFHardwareChange | InvalidPort,
506     };
507 
508     /**
509      * Operations
510      * Used to handle pending state
511      */
512     enum Operation {
513 	PendingInitialize = 0,           // initialize() is pending
514 	PendingCount,
515     };
516 
517     /**
518      * Poll for a pending operation
519      * @param oper Operation to check
520      * @param waitMs Optional time (in milliseconds) to wait for operation completion
521      * @return Error code (0 on success)
522      */
523     unsigned int pollPending(unsigned int oper, unsigned int waitMs = 0);
524 
525     /**
526      * Retrieve the radio device path
527      * @param devicePath Destination buffer
528      * @return Error code (0 on success)
529      */
getInterface(String & devicePath)530     virtual unsigned int getInterface(String& devicePath) const
531 	{ return NotSupported; }
532 
533     /**
534      * Retrieve radio capabilities
535      * @return RadioCapability pointer, 0 if unknown or not implemented
536      */
capabilities()537     virtual const RadioCapability* capabilities() const
538 	{ return m_radioCaps; }
539 
540     /**
541      * Initialize the radio interface.
542      * Any attempt to transmit or receive prior to this operation will return NotInitialized.
543      * @param params Optional parameters list
544      * @return Error code (0 on success)
545      */
546     virtual unsigned int initialize(const NamedList& params = NamedList::empty()) = 0;
547 
548     /**
549      * Set radio loopback
550      * @param name Loopback name (NULL for none)
551      * @return Error code (0 on success)
552      */
553     virtual unsigned int setLoopback(const char* name = 0)
554 	{ return NotSupported; }
555 
556     /**
557      * Set multiple interface parameters.
558      * Each command must start with 'cmd:' to allow the code to detect unhandled commands.
559      * Command sub-params should not start with the prefix
560      * @param params Parameters list
561      * @param shareFate True to indicate all parameters share the fate
562      *  (return on first error, except for Pending), false to process all
563      * @return Error code (0 on success). Failed command(s) will be set in the list
564      *  with cmd_name.code=error_code
565      */
566     virtual unsigned int setParams(NamedList& params, bool shareFate = true) = 0;
567 
568     /**
569      * Update (set/reset) interface data dump
570      * @param dir Direction to update. 0: both, negative: RX only, positive: TX only
571      * @param level Dump level to update. 0: both, negative: interface level (data
572      *  sent/received by the upper layer), positive: device level (data sent to or
573      *  read from radio device)
574      * @param params Optional parameters
575      * @return Error code (0 on success)
576      */
577     virtual unsigned int setDataDump(int dir = 0, int level = 0,
578 	const NamedList* params = 0) = 0;
579 
580     /**
581      * Run internal calibration procedures and/or load calibration parmameters
582      * @return Error code (0 on success)
583      */
calibrate()584     virtual unsigned int calibrate()
585 	{ return NotSupported; }
586 
587     /**
588      * Set the number of ports to be used
589      * @param count The number of ports to be used
590      * @return Error code (0 on success)
591      */
592     virtual unsigned int setPorts(unsigned count) = 0;
593 
594     /**
595      * Return any persistent error codes.
596      * ("Persistent" means a condition of the radio interface itself,
597      * as opposed to a status code related to a specific method call)
598      * @param port Port number to check, or -1 for all ports OR'd together
599      * @return Error(s) mask
600      */
601     virtual unsigned int status(int port = -1) const = 0;
602 
603     /**
604      * Clear all error codes that can be cleared.
605      * Note the not all codes are clearable, like HW failures for example.
606      */
clearErrors()607     virtual void clearErrors()
608 	{ m_lastErr &= ~ClearErrorMask; }
609 
610     /**
611      * Send a frame of complex samples at a given time, interleaved IQ format.
612      * If there are gaps in the sample stream, the RadioInterface must zero-fill.
613      * All ports are sent together in interleaved format; example:
614      * I0 Q0 I1 Q1 I2 Q2 I0 Q0 I1 Q1 I2 Q2, etc for a 3-port system
615      * Block until the send is complete.
616      * Return TooEarly if the blocking time would be too long.
617      * Return TooLate if any of the block is in the past.
618      * @param when Time to schedule the transmission
619      * @param samples Data to send (array of 2 * size * ports floats, interleaved IQ)
620      * @param size The number of sample periods in the samples array
621      * @param powerScale Optional pointer to power scale value
622      * @return Error code (0 on success)
623      */
624     virtual unsigned int send(uint64_t when, float* samples, unsigned size,
625 	float* powerScale = 0) = 0;
626 
627     /**
628      * Receive the next available samples and associated timestamp.
629      * All ports are received together in interleaved format.
630      *  e.g: I0 Q0 I1 Q1 I2 Q2 I0 Q0 I1 Q1 I2 Q2, etc for a 3-port system.
631      * The method will wait for proper timestamp (to be at least requested timestamp).
632      * The caller must increase the timestamp after succesfull read.
633      * The method may return less then requested size.
634      * @param when Input: current timestamp. Output: read data timestamp
635      * @param samples Destination buffer (array of 2 * size * ports floats, interleaved IQ)
636      * @param size Input: requested number of samples. Output: actual number of read samples
637      * @return Error code (0 on success)
638      */
639     virtual unsigned int recv(uint64_t& when, float* samples, unsigned& size) = 0;
640 
641     /**
642      * Receive the next available samples and associated timestamp.
643      * Compensate timestamp difference.
644      * Copy any valid data in the future to auxiliary buffers.
645      * Adjust the timestamp (no need for the caller to do it).
646      * Handles buffer rotation also.
647      * All sample counters (length/offset) are expected in sample periods.
648      * @param when Input: current timestamp. Output: next read data timestamp
649      * @param bufs Buffers to use
650      * @param skippedBufs The number of skipped full buffers
651      * @return Error code (0 on success)
652      */
653     virtual unsigned int read(uint64_t& when, RadioReadBufs& bufs,
654 	unsigned int& skippedBufs);
655 
656     /**
657      * Get the time of the data currently being received from the radio
658      * @param when Destination buffer for requested radio time
659      * @return Error code (0 on success)
660      */
661     virtual unsigned int getRxTime(uint64_t& when) const = 0;
662 
663     /**
664      * Get the time of the the data currently being sent to the radio
665      * @param when Destination buffer for requested radio time
666      * @return Error code (0 on success)
667      */
668     virtual unsigned int getTxTime(uint64_t& when) const = 0;
669 
670     /**
671      * Set the frequency offset
672      * @param offs Frequency offset to set
673      * @param newVal Optional pointer to value set by interface (requested value may
674      *  be adjusted to fit specific device value)
675      * @return Error code (0 on success)
676      */
677     virtual unsigned int setFreqOffset(float offs, float* newVal = 0) = 0;
678 
679     /**
680      * Set the sample rate
681      * @param hz Sample rate value in Hertz
682      * @return Error code (0 on success)
683      */
684     virtual unsigned int setSampleRate(uint64_t hz) = 0;
685 
686     /**
687      * Get the actual sample rate
688      * @param hz Sample rate value in Hertz
689      * @return Error code (0 on success)
690      */
691     virtual unsigned int getSampleRate(uint64_t& hz) const = 0;
692 
693     /**
694      * Set the anti-aliasing filter BW
695      * @param hz Anti-aliasing filter value in Hertz
696      * @return Error code (0 on success)
697      */
698     virtual unsigned int setFilter(uint64_t hz) = 0;
699 
700     /**
701      * Get the actual anti-aliasing filter BW
702      * @param hz Anti-aliasing filter value in Hertz
703      * @return Error code (0 on success)
704      */
705     virtual unsigned int getFilterWidth(uint64_t& hz) const = 0;
706 
707     /**
708      * Set the transmit frequency in Hz
709      * @param hz Transmit frequency value
710      * @return Error code (0 on success)
711      */
712     virtual unsigned int setTxFreq(uint64_t hz) = 0;
713 
714     /**
715      * Readback actual transmit frequency
716      * @param hz Transmit frequency value
717      * @return Error code (0 on success)
718      */
719     virtual unsigned int getTxFreq(uint64_t& hz) const = 0;
720 
721     /**
722      * Set the output power in dBm.
723      * This is power per active port, compensating for internal gain differences.
724      * @param dBm The output power to set
725      * @return Error code (0 on success)
726      */
727     virtual unsigned int setTxPower(unsigned dBm) = 0;
728 
729     /**
730      * Set the receive frequency in Hz
731      * @param hz Receive frequency value
732      * @return Error code (0 on success)
733      */
734     virtual unsigned int setRxFreq(uint64_t hz) = 0;
735 
736     /**
737      * Readback actual receive frequency
738      * @param hz Receive frequency value
739      * @return Error code (0 on success)
740      */
741     virtual unsigned int getRxFreq(uint64_t& hz) const = 0;
742 
743     /**
744      * Set the transmit pre-mixer gain in dB wrt max
745      * @return Error code (0 on success)
746      */
setTxGain1(int val,unsigned port)747     virtual unsigned int setTxGain1(int val, unsigned port)
748 	{ return NotSupported; }
749 
750     /**
751      * Set the transmit post-mixer gain in dB wrt max
752      * @return Error code (0 on success)
753      */
setTxGain2(int val,unsigned port)754     virtual unsigned int setTxGain2(int val, unsigned port)
755 	{ return NotSupported; }
756 
757     /**
758      * Set the receive pre-mixer gain in dB wrt max
759      * @return Error code (0 on success)
760      */
setRxGain1(int val,unsigned port)761     virtual unsigned int setRxGain1(int val, unsigned port)
762 	{ return NotSupported; }
763 
764     /**
765      * Set the receive post-mixer gain in dB wrt max
766      * @return Error code (0 on success)
767      */
setRxGain2(int val,unsigned port)768     virtual unsigned int setRxGain2(int val, unsigned port)
769 	{ return NotSupported; }
770 
771     /**
772      * Automatic tx/rx gain setting
773      * Set post mixer value. Return a value to be used by upper layer
774      * @param tx Direction
775      * @param val Value to set
776      * @param port Port to use
777      * @param newVal Optional pointer to value to use for calculation by the upper layer
778      * @return Error code (0 on success)
779      */
780     virtual unsigned int setGain(bool tx, int val, unsigned int port,
781 	int* newVal = 0) const
782 	{ return NotSupported; }
783 
784     /**
785      * Retrieve the interface name
786      * @return Interface name
787      */
788     virtual const String& toString() const;
789 
790     /**
791      * Complete device info parameters
792      * @param p Destination list
793      * @param full Put full device info
794      * @param retData True to set out pointer in destination, false to add name only
795      */
796     virtual void completeDevInfo(NamedList& p, bool full = false, bool retData = false);
797 
798     /**
799      * Fill (set) error related parameters
800      * @param p Destination list
801      * @param code Error code
802      * @param str Optional error string (not error name)
803      */
804     virtual void setError(NamedList& p, unsigned int code, const char* str = 0);
805 
806     /**
807      * Retrieve the error string associated with a specific code
808      * @param code Error code
809      * @param defVal Optional default value to retrieve if not found
810      * @return Valid TokenDict pointer
811      */
812     static inline const char* errorName(int code, const char* defVal = 0)
813 	{ return lookup(code,errorNameDict(),defVal); }
814 
815     /**
816      * Retrieve the error name dictionary
817      * @return Valid TokenDict pointer
818      */
819     static const TokenDict* errorNameDict();
820 
821 protected:
822     /**
823      * Constructor
824      * @param name Interface name
825      */
826     RadioInterface(const char* name);
827 
828     /**
829      * Set pending state
830      * @param oper Operation to set
831      * @param code Status code
832      */
833     inline void setPending(unsigned int oper, unsigned int code = Pending) {
834 	    Lock lck(m_mutex);
835 	    if (oper < PendingCount)
836 		m_pendingCode[oper] = code;
837 	}
838 
839     unsigned int m_lastErr;               // Last error that appeared during functioning
840     unsigned int m_totalErr;              // All the errors that appeared
841     RadioCapability* m_radioCaps;         // Radio capabilities
842 
843 private:
844     String m_name;
845     Mutex m_mutex;
846     unsigned int m_pendingCode[PendingCount];
847 };
848 
849 
850 /**
851  * @short Radio data file header
852  * This class describes records in radio data files
853  */
854 class YRADIO_API RadioDataDesc
855 {
856 public:
857     /**
858      * Samples data type
859      */
860     enum ElementType {
861 	Float = 0,
862 	Int16 = 1,
863     };
864 
865     /**
866      * Timestamp type
867      */
868     enum TsType {
869 	TsApp = 0,                       // Application level timestamp
870 	TsBoard = 1,                     // Board (device) level timestamp
871     };
872 
873     /**
874      * Constructor
875      * @param eType Element type
876      * @param tsType Racords timestamp type
877      * @param sLen Sample length in elements
878      * @param ports Number of device ports
879      */
880     inline RadioDataDesc(uint8_t eType = Float, uint8_t tsType = TsApp,
881 	uint8_t sLen = 2, uint8_t ports = 1)
m_elementType(eType)882 	: m_elementType(eType), m_sampleLen(sLen), m_ports(ports ? ports : 1),
883 	m_tsType(tsType),
884 #ifdef LITTLE_ENDIAN
885 	m_littleEndian(true)
886 #else
887 	m_littleEndian(false)
888 #endif
889 	{
890 	    m_signature[0] = 'Y';
891 	    m_signature[1] = 'R';
892 	    m_signature[2] = 0;
893 	}
894 
895     uint8_t m_signature[3];              // File signature
896     uint8_t m_elementType;               // Element data type
897     uint8_t m_sampleLen;                 // Sample length in elements
898     uint8_t m_ports;                     // The number of ports
899     uint8_t m_tsType;                    // Records timestamp type
900     bool m_littleEndian;                 // Endiannes
901 };
902 
903 
904 /**
905  * @short Radio data file helper
906  * This class implements utilities used to read or write radio data to/from file
907  * The String contains object name used for debug
908  */
909 class YRADIO_API RadioDataFile : public String
910 {
911 public:
912     /**
913      * Constructor
914      * @param name Name used for debug
915      * @param dropOnError Terminate on file/data error
916      */
917     RadioDataFile(const char* name, bool dropOnError = true);
918 
919     /**
920      * Destructor
921      */
922     virtual ~RadioDataFile();
923 
924     /**
925      * Retrieve data description
926      * @return Data description object
927      */
desc()928     inline const RadioDataDesc& desc() const
929 	{ return m_header; }
930 
931     /**
932      * Check if enabled
933      * @return True if enabled, false otherwise
934      */
valid()935     inline bool valid() const
936 	{ return m_file.valid(); }
937 
938     /**
939      * Check if machine endiannes is the same as file endiannes
940      * @return True if they are the same
941      */
sameEndian()942     inline bool sameEndian() const
943 	{ return m_littleEndian == m_header.m_littleEndian; }
944 
945     /**
946      * Open a file for read/write. Terminate current data dump if any.
947      * Write or read the file header
948      * @param fileName File to open
949      * @param data Data description. Pass a NULL pointer for read or valid data for write
950      * @param dbg Optional DebugEnabler pointer (show debug on failure)
951      * @param error Optional destination for file operation error code
952      * @return True on success, false on failure (read: error set to 0 means
953      *  invalid file size, write: error set to 0 means invalid header)
954      */
955     bool open(const char* fileName, const RadioDataDesc* data,
956 	DebugEnabler* dbg = 0, int* error = 0);
957 
958     /**
959      * Write a record to file
960      * @param ts Record timestamp
961      * @param buf Buffer to write
962      * @param len Buffer length in bytes
963      * @param dbg Optional DebugEnabler pointer (show debug on failure)
964      * @param error Optional destination for file operation error code
965      * @return True on success, false on failure (error set to 0 means invalid length)
966      */
967     bool write(uint64_t ts, const void* buf, uint32_t len, DebugEnabler* dbg = 0,
968 	int* error = 0);
969 
970     /**
971      * Read a record from file
972      * The method don't check the record length, this must be done by the upper layer
973      * @param ts Record timestamp
974      * @param buffer Destination buffer. It will be resized to read data length
975      * @param dbg Optional DebugEnabler pointer (show debug on failure)
976      * @param error Optional destination for file operation error code
977      * @return True on success (empty buffer means file EOF),
978      *  false on failure (error set to 0 means invalid record size)
979      */
980     bool read(uint64_t& ts, DataBlock& buffer, DebugEnabler* dbg = 0, int* error = 0);
981 
982     /**
983      * Terminate data dump, close file
984      * @param dbg Optional DebugEnabler pointer (show terminate message)
985      */
986     void terminate(DebugEnabler* dbg = 0);
987 
988     /**
989      * Convert endiannes
990      * @param buf The buffer to convert
991      * @param bytes Element length in bytes
992      * @return True on success, false if not supported
993      */
994     static bool fixEndian(DataBlock& buf, unsigned int bytes);
995 
996 protected:
997     bool ioError(bool send, DebugEnabler* dbg, int* error, const char* extra);
998 
999     bool m_littleEndian;                 // Machine endiannes
1000     bool m_dropOnError;                  // Terminate (close file) on error
1001     uint32_t m_chunkSize;                // Item size (used to check data validity)
1002     RadioDataDesc m_header;              // File header
1003     File m_file;                         // File to use
1004     DataBlock m_writeBuf;
1005 };
1006 
1007 }; // namespace TelEngine
1008 
1009 #endif /* __YATERADIO_H */
1010 
1011 /* vi: set ts=8 sw=4 sts=4 noet: */
1012