Open Lighting Architecture  0.9.6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RDMCommand.h
Go to the documentation of this file.
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library 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 GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15  *
16  * RDMCommand.h
17  * All the classes that represent RDM commands.
18  * Copyright (C) 2005 Simon Newton
19  */
20 
21 
30 #ifndef INCLUDE_OLA_RDM_RDMCOMMAND_H_
31 #define INCLUDE_OLA_RDM_RDMCOMMAND_H_
32 
33 #include <stdint.h>
34 #include <ola/base/Macro.h>
35 #include <ola/io/ByteString.h>
36 #include <ola/io/OutputStream.h>
37 #include <ola/rdm/CommandPrinter.h>
38 #include <ola/rdm/RDMEnums.h>
39 #include <ola/rdm/RDMPacket.h>
40 #include <ola/rdm/RDMResponseCodes.h>
41 #include <ola/rdm/UID.h>
42 #include <sstream>
43 #include <string>
44 
45 namespace ola {
46 namespace rdm {
47 
59 class RDMCommand {
60  public:
65  // TODO(simon): remove this in favor of the new one in RDMEnums.h
66  typedef enum {
69  GET_COMMAND = 0x20,
71  SET_COMMAND = 0x30,
73  INVALID_COMMAND = 0xff,
75 
76  virtual ~RDMCommand();
77 
89  std::string ToString() const;
90 
97  friend std::ostream& operator<<(std::ostream &out,
98  const RDMCommand &command) {
99  return out << command.ToString();
100  }
101 
110  virtual uint8_t SubStartCode() const { return SUB_START_CODE; }
111 
113  virtual uint8_t MessageLength() const;
114 
116  const UID& SourceUID() const { return m_source; }
117 
119  const UID& DestinationUID() const { return m_destination; }
120 
122  uint8_t TransactionNumber() const { return m_transaction_number; }
123 
125  uint8_t PortIdResponseType() const { return m_port_id; }
126 
128  uint8_t MessageCount() const { return m_message_count; }
129 
131  uint16_t SubDevice() const { return m_sub_device; }
132 
134  virtual RDMCommandClass CommandClass() const = 0;
135 
137  uint16_t ParamId() const { return m_param_id; }
138 
140  unsigned int ParamDataSize() const { return m_data_length; }
141 
143  const uint8_t *ParamData() const { return m_data; }
144 
154  virtual uint16_t Checksum(uint16_t checksum) const { return checksum; }
155 
163  virtual void Print(CommandPrinter *printer,
164  bool summarize,
165  bool unpack_param_data) const {
166  printer->Print(this, summarize, unpack_param_data);
167  }
168 
174  bool operator==(const RDMCommand &other) const;
175 
179  static const uint8_t START_CODE = 0xcc;
180 
187  static RDMCommand *Inflate(const uint8_t *data, unsigned int length);
188 
189  protected:
190  uint8_t m_port_id;
191  UID m_source;
192  UID m_destination;
193  uint8_t m_transaction_number;
194 
198  RDMCommand(const UID &source,
199  const UID &destination,
200  uint8_t transaction_number,
201  uint8_t port_id,
202  uint8_t message_count,
203  uint16_t sub_device,
204  uint16_t param_id,
205  const uint8_t *data,
206  unsigned int length);
207 
208  void SetParamData(const uint8_t *data, unsigned int length);
209 
210  static RDMStatusCode VerifyData(const uint8_t *data,
211  size_t length,
212  RDMCommandHeader *command_message);
213 
214  static RDMCommandClass ConvertCommandClass(uint8_t command_type);
215 
216  private:
217  uint8_t m_message_count;
218  uint16_t m_sub_device;
219  uint16_t m_param_id;
220  uint8_t *m_data;
221  unsigned int m_data_length;
222 
223  static uint16_t CalculateChecksum(const uint8_t *data,
224  unsigned int packet_length);
225 
226  DISALLOW_COPY_AND_ASSIGN(RDMCommand);
227 };
228 
229 
233 class RDMRequest: public RDMCommand {
234  public:
236  public:
242  : has_message_length(false),
243  has_checksum(false),
244  sub_start_code(SUB_START_CODE),
245  message_length(0),
246  message_count(0),
247  checksum(0) {
248  }
249 
250  void SetMessageLength(uint8_t message_length_arg) {
251  has_message_length = true;
252  message_length = message_length_arg;
253  }
254 
255  void SetChecksum(uint16_t checksum_arg) {
256  has_checksum = true;
257  checksum = checksum_arg;
258  }
259 
260  bool has_message_length;
261  bool has_checksum;
262 
263  uint8_t sub_start_code;
264  uint8_t message_length;
265  uint8_t message_count;
266  uint16_t checksum;
267  };
268 
282  RDMRequest(const UID &source,
283  const UID &destination,
284  uint8_t transaction_number,
285  uint8_t port_id,
286  uint16_t sub_device,
287  RDMCommandClass command_class,
288  uint16_t param_id,
289  const uint8_t *data,
290  unsigned int length,
291  const OverrideOptions &options = OverrideOptions());
292 
293  RDMCommandClass CommandClass() const { return m_command_class; }
294 
299  uint8_t PortId() const { return m_port_id; }
300 
305  virtual RDMRequest *Duplicate() const {
306  return new RDMRequest(
307  SourceUID(),
308  DestinationUID(),
310  PortId(),
311  SubDevice(),
312  m_command_class,
313  ParamId(),
314  ParamData(),
315  ParamDataSize(),
316  m_override_options);
317  }
318 
319  virtual void Print(CommandPrinter *printer,
320  bool summarize,
321  bool unpack_param_data) const {
322  printer->Print(this, summarize, unpack_param_data);
323  }
324 
329  bool IsDUB() const;
330 
331  uint8_t SubStartCode() const;
332  uint8_t MessageLength() const;
333  uint16_t Checksum(uint16_t checksum) const;
334 
344  void SetSourceUID(const UID &source_uid) {
345  m_source = source_uid;
346  }
347 
352  void SetTransactionNumber(uint8_t transaction_number) {
353  m_transaction_number = transaction_number;
354  }
355 
360  void SetPortId(uint8_t port_id) {
361  m_port_id = port_id;
362  }
363 
372  static RDMRequest* InflateFromData(const uint8_t *data,
373  unsigned int length);
374 
375  protected:
376  OverrideOptions m_override_options;
377 
378  private:
379  RDMCommandClass m_command_class;
380 };
381 
382 
387  public:
401  RDMGetSetRequest(const UID &source,
402  const UID &destination,
403  uint8_t transaction_number,
404  uint8_t port_id,
405  uint16_t sub_device,
406  RDMCommandClass command_class,
407  uint16_t param_id,
408  const uint8_t *data,
409  unsigned int length,
410  const OverrideOptions &options)
411  : RDMRequest(source, destination, transaction_number, port_id,
412  sub_device, command_class, param_id, data, length, options) {
413  }
414 };
415 
416 
417 template <RDMCommand::RDMCommandClass command_class>
419  public:
420  BaseRDMRequest(const UID &source,
421  const UID &destination,
422  uint8_t transaction_number,
423  uint8_t port_id,
424  uint16_t sub_device,
425  uint16_t param_id,
426  const uint8_t *data,
427  unsigned int length,
428  const OverrideOptions &options = OverrideOptions())
429  : RDMGetSetRequest(source, destination, transaction_number, port_id,
430  sub_device, command_class, param_id, data, length,
431  options) {
432  }
433 
436  SourceUID(),
437  DestinationUID(),
439  PortId(),
440  SubDevice(),
441  ParamId(),
442  ParamData(),
443  ParamDataSize(),
444  m_override_options);
445  }
446 };
447 
448 typedef BaseRDMRequest<RDMCommand::GET_COMMAND> RDMGetRequest;
449 typedef BaseRDMRequest<RDMCommand::SET_COMMAND> RDMSetRequest;
450 
451 
456 class RDMResponse: public RDMCommand {
457  public:
471  RDMResponse(const UID &source,
472  const UID &destination,
473  uint8_t transaction_number,
474  uint8_t response_type,
475  uint8_t message_count,
476  uint16_t sub_device,
477  RDMCommand::RDMCommandClass command_class,
478  uint16_t param_id,
479  const uint8_t *data,
480  unsigned int length)
481  : RDMCommand(source, destination, transaction_number, response_type,
482  message_count, sub_device, param_id, data, length),
483  m_command_class(command_class) {
484  }
485 
486  virtual void Print(CommandPrinter *printer,
487  bool summarize,
488  bool unpack_param_data) const {
489  printer->Print(this, summarize, unpack_param_data);
490  }
491 
497  return new RDMResponse(
498  SourceUID(),
499  DestinationUID(),
501  ResponseType(),
502  MessageCount(),
503  SubDevice(),
504  CommandClass(),
505  ParamId(),
506  ParamData(),
507  ParamDataSize());
508  }
509 
519  uint8_t ResponseType() const { return m_port_id; }
520 
521  RDMCommandClass CommandClass() const { return m_command_class; }
522 
534  void SetDestinationUID(const UID &destination_uid) {
535  m_destination = destination_uid;
536  }
537 
542  void SetTransactionNumber(uint8_t transaction_number) {
543  m_transaction_number = transaction_number;
544  }
545 
553  static const unsigned int MAX_OVERFLOW_SIZE = 4 << 10;
554 
563  static RDMResponse* InflateFromData(const uint8_t *data,
564  size_t length,
565  RDMStatusCode *status_code,
566  const RDMRequest *request = NULL);
567 
576  RDMStatusCode *status_code,
577  const RDMRequest *request = NULL) {
578  return InflateFromData(input.data(), input.size(), status_code, request);
579  }
580 
591  static RDMResponse* CombineResponses(const RDMResponse *response1,
592  const RDMResponse *response2);
593 
594  private:
595  RDMCommand::RDMCommandClass m_command_class;
596 };
597 
598 
603  public:
604  RDMGetSetResponse(const UID &source,
605  const UID &destination,
606  uint8_t transaction_number,
607  uint8_t response_type,
608  uint8_t message_count,
609  uint16_t sub_device,
610  RDMCommand::RDMCommandClass command_class,
611  uint16_t param_id,
612  const uint8_t *data,
613  unsigned int length)
614  : RDMResponse(source, destination, transaction_number, response_type,
615  message_count, sub_device, command_class, param_id, data,
616  length) {
617  }
618 };
619 
620 
621 template <RDMCommand::RDMCommandClass command_class>
623  public:
624  BaseRDMResponse(const UID &source,
625  const UID &destination,
626  uint8_t transaction_number,
627  uint8_t response_type,
628  uint8_t message_count,
629  uint16_t sub_device,
630  uint16_t param_id,
631  const uint8_t *data,
632  unsigned int length)
633  : RDMGetSetResponse(source, destination, transaction_number,
634  response_type, message_count, sub_device,
635  command_class, param_id, data, length) {
636  }
637 };
638 
641 
642 // Helper functions for dealing with RDMCommands
643 // These are mostly used with the RDM-TRI & dummy plugin
644 
648 RDMResponse *NackWithReason(const RDMRequest *request,
649  rdm_nack_reason reason,
650  uint8_t outstanding_messages = 0);
655  const uint8_t *data = NULL,
656  unsigned int length = 0,
657  rdm_response_type type = RDM_ACK,
658  uint8_t outstanding_messages = 0);
659 
664  uint16_t pid,
665  const uint8_t *data,
666  unsigned int length,
667  uint8_t type = RDM_ACK,
668  uint8_t outstanding_messages = 0);
669 
674  public:
675  RDMDiscoveryRequest(const UID &source,
676  const UID &destination,
677  uint8_t transaction_number,
678  uint8_t port_id,
679  uint16_t sub_device,
680  uint16_t param_id,
681  const uint8_t *data,
682  unsigned int length,
683  const OverrideOptions &options = OverrideOptions())
684  : RDMRequest(source,
685  destination,
686  transaction_number,
687  port_id,
688  sub_device,
690  param_id,
691  data,
692  length,
693  options) {
694  }
695 
696  uint8_t PortId() const { return m_port_id; }
697 
698  virtual void Print(CommandPrinter *printer,
699  bool summarize,
700  bool unpack_param_data) const {
701  printer->Print(this, summarize, unpack_param_data);
702  }
703 
704  static RDMDiscoveryRequest* InflateFromData(const uint8_t *data,
705  unsigned int length);
706 };
707 
708 
709 // Because the number of discovery requests is small (3 type) we provide a
710 // helper method for each here.
714 RDMDiscoveryRequest *NewDiscoveryUniqueBranchRequest(
715  const UID &source,
716  const UID &lower,
717  const UID &upper,
718  uint8_t transaction_number,
719  uint8_t port_id = 1);
720 
721 
725 RDMDiscoveryRequest *NewMuteRequest(const UID &source,
726  const UID &destination,
727  uint8_t transaction_number,
728  uint8_t port_id = 1);
729 
733 RDMDiscoveryRequest *NewUnMuteRequest(const UID &source,
734  const UID &destination,
735  uint8_t transaction_number,
736  uint8_t port_id = 1);
737 
738 
743  public:
744  RDMDiscoveryResponse(const UID &source,
745  const UID &destination,
746  uint8_t transaction_number,
747  uint8_t port_id,
748  uint8_t message_count,
749  uint16_t sub_device,
750  uint16_t param_id,
751  const uint8_t *data,
752  unsigned int length)
753  : RDMResponse(source,
754  destination,
755  transaction_number,
756  port_id,
757  message_count,
758  sub_device,
760  param_id,
761  data,
762  length) {
763  }
764 
765  virtual void Print(CommandPrinter *printer,
766  bool summarize,
767  bool unpack_param_data) const {
768  printer->Print(this, summarize, unpack_param_data);
769  }
770 
771  static RDMDiscoveryResponse* InflateFromData(const uint8_t *data,
772  unsigned int length);
773 };
775 } // namespace rdm
776 } // namespace ola
777 #endif // INCLUDE_OLA_RDM_RDMCOMMAND_H_