Open Lighting Architecture  0.9.4
 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 typedef enum {
34  ONE_BYTES = 0x00,
35  TWO_BYTES = 0x01,
36  FOUR_BYTES = 0x02,
37  RES_BYTES = 0x03
38 } dmp_address_size;
39 
40 
41 typedef enum {
42  NON_RANGE = 0x00,
43  RANGE_SINGLE = 0x01,
44  RANGE_EQUAL = 0x02,
45  RANGE_MIXED = 0x03,
46 } dmp_address_type;
47 
48 
49 static const unsigned int MAX_TWO_BYTE = 0xffff;
50 static const unsigned int MAX_ONE_BYTE = 0xff;
51 
52 
53 /*
54  * Return the dmp_address_size that corresponds to a type
55  */
56 template <typename type>
57 dmp_address_size TypeToDMPSize() {
58  switch (sizeof(type)) {
59  case 1:
60  return ONE_BYTES;
61  case 2:
62  return TWO_BYTES;
63  case 4:
64  return FOUR_BYTES;
65  default:
66  return RES_BYTES;
67  }
68 }
69 
70 
71 /*
72  * Return the number of bytes that correspond to a DMPType
73  */
74 unsigned int DMPSizeToByteSize(dmp_address_size size);
75 
76 
77 /*
78  * The Base DMPAddress class.
79  * The addresses represented by this class may be actual or virtual & relative
80  * or absolute, ranged or non-ranged.
81  */
83  public:
84  BaseDMPAddress() {}
85  virtual ~BaseDMPAddress() {}
86 
87  // The start address
88  virtual unsigned int Start() const = 0;
89  // The increment
90  virtual unsigned int Increment() const = 0;
91  // The number of properties referenced
92  virtual unsigned int Number() const = 0;
93 
94  // Size of this address structure
95  virtual unsigned int Size() const {
96  return (IsRange() ? 3 : 1) * BaseSize();
97  }
98 
99  virtual dmp_address_size AddressSize() const = 0;
100 
101  // Pack this address into memory
102  virtual bool Pack(uint8_t *data, unsigned int *length) const = 0;
103 
104  // Write this address to an OutputStream
105  virtual void Write(ola::io::OutputStream *stream) const = 0;
106 
107  // True if this is a range address.
108  virtual bool IsRange() const = 0;
109 
110  protected:
111  virtual unsigned int BaseSize() const = 0;
112 };
113 
114 
115 /*
116  * These type of addresses only reference one property.
117  */
118 template<typename type>
119 class DMPAddress: public BaseDMPAddress {
120  public:
121  explicit DMPAddress(type start):
122  BaseDMPAddress(),
123  m_start(start) {}
124 
125  unsigned int Start() const { return m_start; }
126  unsigned int Increment() const { return 0; }
127  unsigned int Number() const { return 1; }
128  dmp_address_size AddressSize() const { return TypeToDMPSize<type>(); }
129 
130  bool Pack(uint8_t *data, unsigned int *length) const {
131  if (*length < Size()) {
132  *length = 0;
133  return false;
134  }
135  type field = ola::network::HostToNetwork(m_start);
136  memcpy(data, &field, BaseSize());
137  *length = Size();
138  return true;
139  }
140 
141  void Write(ola::io::OutputStream *stream) const {
142  *stream << ola::network::HostToNetwork(m_start);
143  }
144 
145  bool IsRange() const { return false; }
146 
147  protected:
148  unsigned int BaseSize() const { return sizeof(type); }
149 
150  private:
151  type m_start;
152 };
153 
154 
158 
159 /*
160  * Create a new single address
161  */
162 const BaseDMPAddress *NewSingleAddress(unsigned int value);
163 
164 
165 /*
166  * These type of addresses reference multiple properties.
167  */
168 template <typename type>
170  public:
171  RangeDMPAddress(type start,
172  type increment,
173  type number):
174  BaseDMPAddress(),
175  m_start(start),
176  m_increment(increment),
177  m_number(number) {}
178  unsigned int Start() const { return m_start; }
179  unsigned int Increment() const { return m_increment; }
180  unsigned int Number() const { return m_number; }
181  dmp_address_size AddressSize() const { return TypeToDMPSize<type>(); }
182 
183  bool Pack(uint8_t *data, unsigned int *length) const {
184  if (*length < Size()) {
185  *length = 0;
186  return false;
187  }
188  type field[3];
189  field[0] = ola::network::HostToNetwork(m_start);
190  field[1] = ola::network::HostToNetwork(m_increment);
191  field[2] = ola::network::HostToNetwork(m_number);
192  memcpy(data, &field, Size());
193  *length = Size();
194  return true;
195  }
196 
197  void Write(ola::io::OutputStream *stream) const {
198  type field[3];
199  field[0] = ola::network::HostToNetwork(m_start);
200  field[1] = ola::network::HostToNetwork(m_increment);
201  field[2] = ola::network::HostToNetwork(m_number);
202  stream->Write(reinterpret_cast<uint8_t*>(&field), Size());
203  }
204 
205  bool IsRange() const { return true; }
206 
207  protected:
208  unsigned int BaseSize() const { return sizeof(type); }
209 
210  private:
211  type m_start, m_increment, m_number;
212 };
213 
214 
218 
219 
220 /*
221  * Create a new range address.
222  */
223 const BaseDMPAddress *NewRangeAddress(unsigned int value,
224  unsigned int increment,
225  unsigned int number);
226 
227 /*
228  * Decode an Address
229  */
230 const BaseDMPAddress *DecodeAddress(dmp_address_size size,
231  dmp_address_type type,
232  const uint8_t *data,
233  unsigned int *length);
234 
235 
236 /*
237  * A DMPAddressData object, this hold an address/data pair
238  * @param type either DMPAddress<> or RangeDMPAddress<>
239  */
240 template <typename type>
242  public:
243  DMPAddressData(const type *address,
244  const uint8_t *data,
245  unsigned int length):
246  m_address(address),
247  m_data(data),
248  m_length(length) {}
249 
250  const type *Address() const { return m_address; }
251  const uint8_t *Data() const { return m_data; }
252  unsigned int Size() const { return m_address->Size() + m_length; }
253 
254  // Pack the data into a buffer
255  bool Pack(uint8_t *data, unsigned int *length) const {
256  if (!m_data)
257  return false;
258 
259  unsigned int total = *length;
260  if (!m_address->Pack(data, length)) {
261  length = 0;
262  return false;
263  }
264  if (total - *length < m_length) {
265  length = 0;
266  return false;
267  }
268  memcpy(data + *length, m_data, m_length);
269  *length += m_length;
270  return true;
271  }
272 
273  void Write(ola::io::OutputStream *stream) const {
274  if (!m_data)
275  return;
276 
277  m_address->Write(stream);
278  stream->Write(m_data, m_length);
279  }
280 
281  private:
282  const type *m_address;
283  const uint8_t *m_data;
284  unsigned int m_length;
285 };
286 } // namespace e131
287 } // namespace plugin
288 } // namespace ola
289 #endif // PLUGINS_E131_E131_DMPADDRESS_H_