Open Lighting Architecture
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DMPAddress.h
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU Library General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15  *
16  * DMPAddress.h
17  * Defines the DMP property address types
18  * Copyright (C) 2007 Simon Newton
19  */
20 
21 #ifndef PLUGINS_E131_E131_DMPADDRESS_H_
22 #define PLUGINS_E131_E131_DMPADDRESS_H_
23 
24 #include <stdint.h>
25 #include <string.h>
26 #include "ola/io/OutputStream.h"
27 #include "ola/network/NetworkUtils.h"
28 
29 namespace ola {
30 namespace plugin {
31 namespace e131 {
32 
33 using ola::network::HostToNetwork;
34 
35 typedef enum {
36  ONE_BYTES = 0x00,
37  TWO_BYTES = 0x01,
38  FOUR_BYTES = 0x02,
39  RES_BYTES = 0x03
40 } dmp_address_size;
41 
42 
43 typedef enum {
44  NON_RANGE = 0x00,
45  RANGE_SINGLE = 0x01,
46  RANGE_EQUAL = 0x02,
47  RANGE_MIXED = 0x03,
48 } dmp_address_type;
49 
50 
51 static const unsigned int MAX_TWO_BYTE = 0xffff;
52 static const unsigned int MAX_ONE_BYTE = 0xff;
53 
54 
55 /*
56  * Return the dmp_address_size that corresponds to a type
57  */
58 template <typename type>
59 dmp_address_size TypeToDMPSize() {
60  switch (sizeof(type)) {
61  case 1:
62  return ONE_BYTES;
63  case 2:
64  return TWO_BYTES;
65  case 4:
66  return FOUR_BYTES;
67  default:
68  return RES_BYTES;
69  }
70 }
71 
72 
73 /*
74  * Return the number of bytes that correspond to a DMPType
75  */
76 unsigned int DMPSizeToByteSize(dmp_address_size size);
77 
78 
79 /*
80  * The Base DMPAddress class.
81  * The addresses represented by this class may be actual or virtual & relative
82  * or absolute, ranged or non-ranged.
83  */
85  public:
86  BaseDMPAddress() {}
87  virtual ~BaseDMPAddress() {}
88 
89  // The start address
90  virtual unsigned int Start() const = 0;
91  // The increment
92  virtual unsigned int Increment() const = 0;
93  // The number of properties referenced
94  virtual unsigned int Number() const = 0;
95 
96  // Size of this address structure
97  virtual unsigned int Size() const {
98  return (IsRange() ? 3 : 1) * BaseSize();
99  }
100 
101  virtual dmp_address_size AddressSize() const = 0;
102 
103  // Pack this address into memory
104  virtual bool Pack(uint8_t *data, unsigned int *length) const = 0;
105 
106  // Write this address to an OutputStream
107  virtual void Write(ola::io::OutputStream *stream) const = 0;
108 
109  // True if this is a range address.
110  virtual bool IsRange() const = 0;
111 
112  protected:
113  virtual unsigned int BaseSize() const = 0;
114 };
115 
116 
117 /*
118  * These type of addresses only reference one property.
119  */
120 template<typename type>
121 class DMPAddress: public BaseDMPAddress {
122  public:
123  explicit DMPAddress(type start):
124  BaseDMPAddress(),
125  m_start(start) {}
126 
127  unsigned int Start() const { return m_start; }
128  unsigned int Increment() const { return 0; }
129  unsigned int Number() const { return 1; }
130  dmp_address_size AddressSize() const { return TypeToDMPSize<type>(); }
131 
132  bool Pack(uint8_t *data, unsigned int *length) const {
133  if (*length < Size()) {
134  *length = 0;
135  return false;
136  }
137  type field = HostToNetwork(m_start);
138  memcpy(data, &field, BaseSize());
139  *length = Size();
140  return true;
141  }
142 
143  void Write(ola::io::OutputStream *stream) const {
144  *stream << HostToNetwork(m_start);
145  }
146 
147  bool IsRange() const { return false; }
148 
149  protected:
150  unsigned int BaseSize() const { return sizeof(type); }
151 
152  private:
153  type m_start;
154 };
155 
156 
160 
161 /*
162  * Create a new single address
163  */
164 const BaseDMPAddress *NewSingleAddress(unsigned int value);
165 
166 
167 /*
168  * These type of addresses reference multiple properties.
169  */
170 template <typename type>
172  public:
173  RangeDMPAddress(type start,
174  type increment,
175  type number):
176  BaseDMPAddress(),
177  m_start(start),
178  m_increment(increment),
179  m_number(number) {}
180  unsigned int Start() const { return m_start; }
181  unsigned int Increment() const { return m_increment; }
182  unsigned int Number() const { return m_number; }
183  dmp_address_size AddressSize() const { return TypeToDMPSize<type>(); }
184 
185  bool Pack(uint8_t *data, unsigned int *length) const {
186  if (*length < Size()) {
187  *length = 0;
188  return false;
189  }
190  type field[3];
191  field[0] = HostToNetwork(m_start);
192  field[1] = HostToNetwork(m_increment);
193  field[2] = HostToNetwork(m_number);
194  memcpy(data, &field, Size());
195  *length = Size();
196  return true;
197  }
198 
199  void Write(ola::io::OutputStream *stream) const {
200  type field[3];
201  field[0] = HostToNetwork(m_start);
202  field[1] = HostToNetwork(m_increment);
203  field[2] = HostToNetwork(m_number);
204  stream->Write(reinterpret_cast<uint8_t*>(&field), Size());
205  }
206 
207  bool IsRange() const { return true; }
208 
209  protected:
210  unsigned int BaseSize() const { return sizeof(type); }
211 
212  private:
213  type m_start, m_increment, m_number;
214 };
215 
216 
220 
221 
222 /*
223  * Create a new range address.
224  */
225 const BaseDMPAddress *NewRangeAddress(unsigned int value,
226  unsigned int increment,
227  unsigned int number);
228 
229 /*
230  * Decode an Address
231  */
232 const BaseDMPAddress *DecodeAddress(dmp_address_size size,
233  dmp_address_type type,
234  const uint8_t *data,
235  unsigned int &length);
236 
237 
238 /*
239  * A DMPAddressData object, this hold an address/data pair
240  * @param type either DMPAddress<> or RangeDMPAddress<>
241  */
242 template <typename type>
244  public:
245  DMPAddressData(const type *address,
246  const uint8_t *data,
247  unsigned int length):
248  m_address(address),
249  m_data(data),
250  m_length(length) {}
251 
252  const type *Address() const { return m_address; }
253  const uint8_t *Data() const { return m_data; }
254  unsigned int Size() const { return m_address->Size() + m_length; }
255 
256  // Pack the data into a buffer
257  bool Pack(uint8_t *data, unsigned int *length) const {
258  if (!m_data)
259  return false;
260 
261  unsigned int total = *length;
262  if (!m_address->Pack(data, length)) {
263  length = 0;
264  return false;
265  }
266  if (total - *length < m_length) {
267  length = 0;
268  return false;
269  }
270  memcpy(data + *length, m_data, m_length);
271  *length += m_length;
272  return true;
273  }
274 
275  void Write(ola::io::OutputStream *stream) const {
276  if (!m_data)
277  return;
278 
279  m_address->Write(stream);
280  stream->Write(m_data, m_length);
281  }
282 
283  private:
284  const type *m_address;
285  const uint8_t *m_data;
286  unsigned int m_length;
287 };
288 } // namespace e131
289 } // namespace plugin
290 } // namespace ola
291 #endif // PLUGINS_E131_E131_DMPADDRESS_H_