File: codeplug.hh

package info (click to toggle)
qdmr 0.13.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 22,236 kB
  • sloc: cpp: 93,672; xml: 10,526; python: 1,108; makefile: 78; sh: 10
file content (381 lines) | stat: -rw-r--r-- 17,057 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
#ifndef CODEPLUG_HH
#define CODEPLUG_HH

#include <QObject>
#include <QHash>
#include "dfufile.hh"
#include "transferflags.hh"

class Config;
class ConfigItem;
class SatelliteDatabase;


/** This class defines the interface all device-specific code-plugs must implement.
 * Device-specific codeplugs are derived from the common configuration and implement the
 * construction/parsing of the device specific binary configuration. */
class Codeplug: public DFUFile
{
  Q_OBJECT

public:
  /** Certain flags passed to CodePlug::encode to control the transfer and encoding of the
   * codeplug. */
  class Flags: public TransferFlags {
  public:
    /** Default constructor, enables code-plug update and disables automatic GPS/APRS and roaming. */
    Flags();

  public:
    /** If @c true, the codeplug will first be downloaded from the device, updated from the
     * abstract config and then written back to the device. This maintains the user-settings
     * made within the device or manufacturer CPS. If @c false, the code-plug gets overridden
     * entirely using some default settings. Default @c true. */
    bool updateCodeplug() const;
    /** Sets if the codeplug gets updated. */
    void setUpdateCodeplug(bool enable);

    /** If @c true enables GPS when there is a GPS or APRS system defined that is used by any
     * channel. This may cause automatic transmissions, hence the default is @c false. */
    bool autoEnableGPS() const;
    /** Sets if the GPS gets enabled automatically. */
    void setAutoEnableGPS(bool enable);

    /** If @c true enables automatic roaming when there is a roaming zone defined that is used by any
     * channel. This may cause automatic transmissions, hence the default is @c false. */
    bool autoEnableRoaming() const;
    /** Sets if roaming gets enabled automatically. */
    void setAutoEnableRoaming(bool enable);

  protected:
    bool _updateCodeplug;
    bool _autoEnableGPS;
    bool _autoEnableRoaming;
  };


  /** Represents the abstract base class of all codeplug elements.
   *
   * That is a memory region within the codeplug that encodes a specific element. E.g., channels,
   * contacts, zones, etc. This class provides some helper methods to access specific members of
   * the element.
   *
   * @since 0.9.0 */
  class Element
  {
  protected:
    /** Base class for Offsets. */
    struct Offset {
      /** Some type to specify a bit offset. That is the byte-offset and bit of that byte. */
      struct Bit {
        /** The byte offset. */
        const unsigned int byte;
        /** The bit within the byte. */
        const unsigned int bit;

        /** Implements a simple increment. */
        inline Bit operator+ (unsigned int bits) const {
          unsigned int tmp = 8 * byte + (7-bit) + bits;
          return {tmp/8, (7 - (tmp % 8))};
        }

        /** Implements a simple increment. */
        inline Bit operator- (unsigned int bits) const {
          unsigned int tmp = 8 * byte + (7-bit) - bits;
          return {tmp/8, (7 - (tmp % 8))};
        }
      };
    };

  public:
    /** Base class for Limits. */
    struct Limit {
      /** Holds a range of values [min, max]. */
      template <class T> struct Range {
        /// Lower bound.
        const T min;
        /// Upper bound.
        const T max;
        /// Limits the value to the range.
        inline T limit(const T &value) const {
          return std::min(max, std::max(min, value));
        }
        /// Checks if value is in range
        inline bool in(const T &value) const {
          return (value <= max) && (value >= min);
        }
      };
    };

  protected:
    /** Hidden constructor.
     * @param ptr Specifies the pointer to the element within the codeplug.
     * @param size Specifies the size of the element in bytes. */
    Element(uint8_t *ptr, size_t size);

  public:
    /** Copy constructor. */
    Element(const Element &other);
    /** Destructor. */
    virtual ~Element();

    /** Copy assignment. */
    Element &operator=(const Element &other);

    /** Returns @c true if the pointer is not null. */
    virtual bool isValid() const;
    /** Abstract method to reset the element within the codeplug. Any device specific element
     * should implement this method. */
    virtual void clear();

    /** Fills the memsets the entire element to the given value. */
    bool fill(uint8_t value, unsigned offset=0, int size=-1);

    /** Reads a specific bit at the given byte-offset. */
    bool getBit(const Offset::Bit &offset) const;
    /** Reads a specific bit at the given byte-offset. */
    bool getBit(unsigned offset, unsigned bit) const;
    /** Sets a specific bit at the given byte-offset. */
    void setBit(const Offset::Bit &offset, bool value=true);
    /** Sets a specific bit at the given byte-offset. */
    void setBit(unsigned offset, unsigned bit, bool value=true);
    /** Clears a specific bit at the given byte-offset. */
    void clearBit(unsigned offset, unsigned bit);
    /** Clears a specific bit. */
    void clearBit(const Offset::Bit &offset);

    /** Reads a 2bit unsigned integer at the given bit-offset. */
    uint8_t getUInt2(const Offset::Bit &offset) const;
    /** Reads a 2bit unsigned integer at the given byte- and bit-offset. */
    uint8_t getUInt2(unsigned offset, unsigned bit) const;
    /** Stores a 2bit unsigned integer at the given bit-offset. */
    void setUInt2(const Offset::Bit &offset, uint8_t value);
    /** Stores a 2bit unsigned integer at the given byte- and bit-offset. */
    void setUInt2(unsigned offset, unsigned bit, uint8_t value);

    /** Reads a 3bit unsigned integer at the given bit-offset. */
    uint8_t getUInt3(const Offset::Bit &offset) const;
    /** Reads a 3bit unsigned integer at the given byte- and bit-offset. */
    uint8_t getUInt3(unsigned offset, unsigned bit) const;
    /** Stores a 3bit unsigned integer at the given bit-offset. */
    void setUInt3(const Offset::Bit &offset, uint8_t value);
    /** Stores a 3bit unsigned integer at the given byte- and bit-offset. */
    void setUInt3(unsigned offset, unsigned bit, uint8_t value);

    /** Reads a 4bit unsigned integer at the given bit-offset. */
    uint8_t getUInt4(const Offset::Bit &offset) const;
    /** Reads a 4bit unsigned integer at the given byte- and bit-offset. */
    uint8_t getUInt4(unsigned offset, unsigned bit) const;
    /** Stores a 4bit unsigned integer at the given bit-offset. */
    void setUInt4(const Offset::Bit &offset, uint8_t value);
    /** Stores a 4bit unsigned integer at the given byte- and bit-offset. */
    void setUInt4(unsigned offset, unsigned bit, uint8_t value);

    /** Reads a 5bit unsigned integer at the given byte- and bit-offset. */
    uint8_t getUInt5(const Offset::Bit &offset) const;
    /** Reads a 5bit unsigned integer at the given byte- and bit-offset. */
    uint8_t getUInt5(unsigned offset, unsigned bit) const;
    /** Stores a 5bit iunsinged nteger at the given byte- and bit-offset. */
    void setUInt5(const Offset::Bit &offset, uint8_t value);
    /** Stores a 5bit iunsinged nteger at the given byte- and bit-offset. */
    void setUInt5(unsigned offset, unsigned bit, uint8_t value);

    /** Reads a 6bit unsigned integer at the given byte- and bit-offset. */
    uint8_t getUInt6(const Offset::Bit &offset) const;
    /** Reads a 6bit unsigned integer at the given byte- and bit-offset. */
    uint8_t getUInt6(unsigned offset, unsigned bit) const;
    /** Stores a 6bit unsigned integer at the given byte- and bit-offset. */
    void setUInt6(const Offset::Bit &offset, uint8_t value);
    /** Stores a 6bit unsigned integer at the given byte- and bit-offset. */
    void setUInt6(unsigned offset, unsigned bit, uint8_t value);

    /** Reads a 8bit unsigned integer at the given byte- and bit-offset. */
    uint8_t getUInt8(unsigned offset) const;
    /** Reads a 8bit unsigned integer at the given byte- and bit-offset. */
    void setUInt8(unsigned offset, uint8_t value);
    /** Reads a 8bit signed integer at the given byte- and bit-offset. */
    int8_t getInt8(unsigned offset) const;
    /** Reads a 8bit signed integer at the given byte- and bit-offset. */
    void setInt8(unsigned offset, int8_t value);

    /** Reads a 16bit big-endian unsigned integer at the given byte-offset. */
    uint16_t getUInt16_be(unsigned offset) const;
    /** Reads a 16bit little-endian unsigned integer at the given byte-offset. */
    uint16_t getUInt16_le(unsigned offset) const;
    /** Stores a 16bit big-endian unsigned integer at the given byte-offset. */
    void setUInt16_be(unsigned offset, uint16_t value);
    /** Stores a 16bit little-endian unsigned integer at the given byte-offset. */
    void setUInt16_le(unsigned offset, uint16_t value);

    /** Reads a 24bit big-endian unsigned integer at the given byte-offset. */
    uint32_t getUInt24_be(unsigned offset) const;
    /** Reads a 24bit little-endian unsigned integer at the given byte-offset. */
    uint32_t getUInt24_le(unsigned offset) const;
    /** Stores a 24bit big-endian unsigned integer at the given byte-offset. */
    void setUInt24_be(unsigned offset, uint32_t value);
    /** Stores a 24bit little-endian unsigned integer at the given byte-offset. */
    void setUInt24_le(unsigned offset, uint32_t value);

    /** Reads a 32bit big-endian unsigned integer at the given byte-offset. */
    uint32_t getUInt32_be(unsigned offset) const;
    /** Reads a 32bit little-endian unsigned integer at the given byte-offset. */
    uint32_t getUInt32_le(unsigned offset) const;
    /** Stores a 32bit big-endian unsigned integer at the given byte-offset. */
    void setUInt32_be(unsigned offset, uint32_t value);
    /** Stores a 32bit little-endian unsigned integer at the given byte-offset. */
    void setUInt32_le(unsigned offset, uint32_t value);

    /** Reads a 64bit big-endian unsigned integer at the given byte-offset. */
    uint64_t getUInt64_be(unsigned offset) const;
    /** Reads a 64bit little-endian unsigned integer at the given byte-offset. */
    uint64_t getUInt64_le(unsigned offset) const;
    /** Stores a 64bit big-endian unsigned integer at the given byte-offset. */
    void setUInt64_be(unsigned offset, uint64_t value);
    /** Stores a 64bit little-endian unsigned integer at the given byte-offset. */
    void setUInt64_le(unsigned offset, uint64_t value);

    /** Reads a 2-digit (1-byte/8bit) BDC value in big-endian at the given byte-offset. */
    uint8_t getBCD2(unsigned offset) const;
    /** Stores a 2-digit (1-byte/8bit) BDC value in big-endian at the given byte-offset. */
    void setBCD2(unsigned offset, uint8_t value);

    /** Reads a 4-digit (2-byte/16bit) BDC value in big-endian at the given byte-offset. */
    uint16_t getBCD4_be(unsigned offset) const;
    /** Stores a 4-digit (2-byte/16bit) BDC value in big-endian at the given byte-offset. */
    void setBCD4_be(unsigned offset, uint16_t value);
    /** Reads a 4-digit (2-byte/16bit) BDC value in little-endian at the given byte-offset. */
    uint16_t getBCD4_le(unsigned offset) const;
    /** Stores a 4-digit (1-byte/16bit) BDC value in little-endian at the given byte-offset. */
    void setBCD4_le(unsigned offset, uint16_t value);

    /** Reads a 8-digit (4-byte/32bit) BDC value in big-endian at the given byte-offset. */
    uint32_t getBCD8_be(unsigned offset) const;
    /** Stores a 8-digit (4-byte/32bit) BDC value in big-endian at the given byte-offset. */
    void setBCD8_be(unsigned offset, uint32_t value);
    /** Reads a 8-digit (4-byte/32bit) BDC value in little-endian at the given byte-offset. */
    uint32_t getBCD8_le(unsigned offset) const;
    /** Stores a 8-digit (4-byte/32bit) BDC value in little-endian at the given byte-offset. */
    void setBCD8_le(unsigned offset, uint32_t value);

    /** Reads up to @c maxlen ASCII chars at the given byte-offset using @c eos as the string termination char. */
    QString readASCII(unsigned offset, unsigned maxlen, uint8_t eos=0x00) const;
    /** Stores up to @c maxlen ASCII chars at the given byte-offset using @c eos as the string termination char.
     * The stored string gets padded with @c eos to @c maxlen. */
    void writeASCII(unsigned offset, const QString &txt, unsigned maxlen, uint8_t eos=0x00);

    /** Reads up to @c maxlen unicode chars at the given byte-offset using @c eos as the string termination char. */
    QString readUnicode(unsigned offset, unsigned maxlen, uint16_t eos=0x0000) const;
    /** Stores up to @c maxlen unicode chars at the given byte-offset using @c eos as the string termination char.
     * The stored string gets padded with @c eos to @c maxlen. */
    void writeUnicode(unsigned offset, const QString &txt, unsigned maxlen, uint16_t eos=0x0000);

  protected:
    /** Holds the pointer to the element. */
    uint8_t *_data;
    /** Holds the size of the element. */
    size_t _size;
  };

  /** Base class for all codeplug contexts.
   * Each device specific codeplug may extend this class to allow for device specific elements to
   * be indexed in a separate index. By default tables for @c DigitalContact, @c RXGroupList,
   * @c Channel, @c Zone and @c ScanList are defined. For any other type, an additional table must
   * be defined first using @c addTable.
   * @since 0.9.0 */
  class Context
  {
  public:
    /** Empty constructor. */
    explicit Context(Config *config);

    /** Returns the reference to the config object. */
    Config *config() const;

    /** Returns a reference to the satellite database. */
    SatelliteDatabase *satellites() const;

    /** Resolves the given index for the specifies element type.
     * @returns @c nullptr if the index is not defined or the type is unknown. */
    ConfigItem *obj(const QMetaObject *elementType, unsigned idx);
    /** Returns the index for the given object.
     * @returns -1 if no index is associated with the object or its type is unknown. */
    int index(ConfigItem *obj);
    /** Associates the given object with the given index. */
    bool add(ConfigItem *obj, unsigned idx);

    /** Adds a table for the given type. */
    bool addTable(const QMetaObject *obj);
    /** Returns @c true if a table is defined for the given type. */
    bool hasTable(const QMetaObject *obj) const;

    /** Returns the object associated by the given index and type. */
    template <class T>
    T* get(unsigned idx) {
      return this->obj(&(T::staticMetaObject), idx)->template as<T>();
    }

    /** Returns @c true, if the given index is defined for the specified type. */
    template <class T>
    bool has(unsigned idx) {
      return nullptr != this->obj(&(T::staticMetaObject), idx)->template as<T>();
    }

    /** Returns the number of elements for the specified type. */
    template <class T>
    unsigned int count() {
      return getTable(&T::staticMetaObject).indices.size();
    }

  protected:
    /** Internal used table type to associate objects and indices. */
    class Table {
    public:
      /** The index->object map. */
      QHash<unsigned, ConfigItem *> objects;
      /** The object->index map. */
      QHash<ConfigItem *, unsigned> indices;
    };

  protected:
    /** Returns a reference to the table for the given type. */
    Table &getTable(const QMetaObject *obj);

  protected:
    /** A weak reference to the config object. */
    Config *_config;
    /** A weak reference to the satellite database. */
    SatelliteDatabase *_satellites;
    /** Table of tables. */
    QHash<QString, Table> _tables;
  };

protected:
  /** Hidden default constructor. */
  explicit Codeplug(QObject *parent=nullptr);

public:
  /** Destructor. */
  virtual ~Codeplug();

  /** Indexes all elements of the codeplug.
   * This method must be implemented by any device or vendor specific codeplug to map config
   * objects to indices used within the binary codeplug to address each element (e.g., channels,
   * contacts etc.). */
  virtual bool index(Config *config, Context &ctx, const ErrorStack &err=ErrorStack()) const = 0;

  /** Decodes a binary codeplug to the given abstract configuration @c config.
   * This must be implemented by the device-specific codeplug. */
  virtual bool decode(Config *config, const ErrorStack &err=ErrorStack()) = 0;
  /** Retruns a post-processed configuration of the decoded config. By default, the passed
   * config is returned. */
  virtual bool postprocess(Config *config, const ErrorStack &err=ErrorStack()) const;

  /** Retruns a prepared configuration for this particular radio. All unsupported featrues are
   *  removed from the copy. The default implementation only copies the config. */
  virtual Config *preprocess(Config *config, const ErrorStack &err=ErrorStack()) const;
  /** Encodes a given abstract configuration (@c config) to the device specific binary code-plug.
   * This must be implemented by the device-specific codeplug. */
  virtual bool encode(Config *config, const Flags &flags=Flags(), const ErrorStack &err=ErrorStack()) = 0;
};

#endif // CODEPLUG_HH