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
|