Index: include/libroarlight/roardmx.h
===================================================================
--- include/libroarlight/roardmx.h	(revision 5976)
+++ include/libroarlight/roardmx.h	(revision 6001)
@@ -99,4 +99,15 @@
 #define ROAR_ROARDMX_EVENT_USER15   0x3F /* User defined event #15 */
 
+/* subcommands for ROAR_ROARDMX_TYPE_CONTROL: */
+#define ROAR_ROARDMX_CTL_VERSION    0x00 /* Version of Codec */
+#define ROAR_ROARDMX_CTL_SYNC       0x01 /* Sync state */
+
+/* Flags for ROAR_ROARDMX_CTL_SYNC: */
+#define ROAR_ROARDMX_SYNC_DIRTY     0x01 /* global state is not sync, some more data needs to be send first */
+#define ROAR_ROARDMX_SYNC_CLEAN     0x02 /* global state is sync */
+#define ROAR_ROARDMX_SYNC_SOF       0x03 /* start of frame */
+#define ROAR_ROARDMX_SYNC_EOF       0x04 /* end of frame */
+#define ROAR_ROARDMX_SYNC_CLOCK     0x80 /* clock tick */
+
 // Data format on the wire:
 /*
@@ -130,5 +141,13 @@
  * (beat, on, off, hold) and the lower 6 bits to the type of te event.
  *
- * CONTROL: not implemented.
+ * CONTROL: transmit other control information.
+ * The body consists of a version byte followed by a command byte.
+ * The version byte is always zero by this standard.
+ * The command byte is one of ROAR_ROARDMX_CTL_*
+ * The rest of body depends on both the version and command byte.
+ * For command=VERSION packets the rest of the body is a single byte with the value
+ * of zero as of this standard.
+ * For command=SYNC packets the rest of the body is a single byte which is a bitarray
+ * for flags defined above as ROAR_ROARDMX_SYNC_*.
  */
 
@@ -191,5 +210,9 @@
 
 // * CONTROL:
-// Not yet supported.
+int roar_roardmx_message_new_version(struct roar_roardmx_message * mes, uint8_t version);
+int roar_roardmx_message_new_sync(struct roar_roardmx_message * mes, uint8_t flags);
+int roar_roardmx_message_get_subcommand(struct roar_roardmx_message * mes);
+int roar_roardmx_message_get_ctl_version(struct roar_roardmx_message * mes);
+int roar_roardmx_message_get_ctl_flags(struct roar_roardmx_message * mes);
 
 #endif
Index: libroarlight/roardmx.c
===================================================================
--- libroarlight/roardmx.c	(revision 5978)
+++ libroarlight/roardmx.c	(revision 6001)
@@ -561,5 +561,91 @@
 
 // * CONTROL:
-// Not yet supported.
+static inline int roar_roardmx_message_new_control(struct roar_roardmx_message * mes, uint8_t subcommand) {
+ BCHK(mes);
+
+ if ( roar_roardmx_message_new(mes) == -1 )
+  return -1;
+
+ mes->type = ROAR_ROARDMX_TYPE_CONTROL;
+ mes->data[3] = 0; // version
+ mes->data[4] = subcommand;
+ mes->length  = 2;
+
+ return 0;
+}
+
+int roar_roardmx_message_new_version(struct roar_roardmx_message * mes, uint8_t version) {
+ BCHK(mes);
+
+ if ( version != (uint8_t)0 ) {
+  roar_err_set(ROAR_ERROR_NSVERSION);
+  return -1;
+ }
+
+ if ( roar_roardmx_message_new_control(mes, ROAR_ROARDMX_CTL_VERSION) == -1 )
+  return -1;
+
+ mes->data[5] = version;
+ mes->length  = 3;
+
+ return 0;
+}
+
+int roar_roardmx_message_new_sync(struct roar_roardmx_message * mes, uint8_t flags) {
+ BCHK(mes);
+
+ if ( roar_roardmx_message_new_control(mes, ROAR_ROARDMX_CTL_VERSION) == -1 )
+  return -1;
+
+ mes->data[5] = flags;
+ mes->length  = 3;
+
+ return 0;
+}
+
+int roar_roardmx_message_get_subcommand(struct roar_roardmx_message * mes) {
+ BCHK(mes);
+
+ if ( mes->type != ROAR_ROARDMX_TYPE_CONTROL ) {
+  roar_err_set(ROAR_ERROR_TYPEMM);
+  return -1;
+ }
+
+ if ( mes->length < 2 ) {
+  roar_err_set(ROAR_ERROR_PROTO);
+  return -1;
+ }
+
+ if ( mes->data[3] != 0 ) {
+  roar_err_set(ROAR_ERROR_NSVERSION);
+  return -1;
+ }
+
+ return mes->data[4];
+}
+
+static inline int roar_roardmx_message_get_ctl_byte5(struct roar_roardmx_message * mes, uint8_t subtype) {
+ BCHK(mes);
+
+ if ( mes->type != ROAR_ROARDMX_TYPE_CONTROL ) {
+  roar_err_set(ROAR_ERROR_TYPEMM);
+  return -1;
+ }
+
+ if ( roar_roardmx_message_get_subcommand(mes) != (int)(unsigned)subtype ) {
+  roar_err_set(ROAR_ERROR_TYPEMM);
+  return -1;
+ }
+
+ return mes->data[5];
+}
+
+int roar_roardmx_message_get_ctl_version(struct roar_roardmx_message * mes) {
+ return roar_roardmx_message_get_ctl_byte5(mes, ROAR_ROARDMX_CTL_VERSION);
+}
+
+int roar_roardmx_message_get_ctl_flags(struct roar_roardmx_message * mes) {
+ return roar_roardmx_message_get_ctl_byte5(mes, ROAR_ROARDMX_CTL_SYNC);
+}
 
 //ll
