168 lines
5.9 KiB
C
168 lines
5.9 KiB
C
/**
|
|
* E1.31 (sACN) library for C/C++
|
|
* Hugo Hromic - http://github.com/hhromic
|
|
*
|
|
* Some content of this file is based on:
|
|
* https://github.com/forkineye/E131/blob/master/E131.h
|
|
* https://github.com/forkineye/E131/blob/master/E131.cpp
|
|
*
|
|
* Copyright 2016 Hugo Hromic
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef _E131_H
|
|
#define _E131_H
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <sys/types.h>
|
|
|
|
#ifndef _WIN32
|
|
#include <netinet/in.h>
|
|
#else
|
|
#include <WinSock2.h>
|
|
#endif
|
|
|
|
#ifdef __GNUC__
|
|
#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
|
|
#endif
|
|
|
|
#ifdef _MSC_VER
|
|
#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
|
|
#endif
|
|
|
|
#if defined(_MSC_VER)
|
|
#include <BaseTsd.h>
|
|
typedef SSIZE_T ssize_t;
|
|
#endif
|
|
|
|
/* E1.31 Public Constants */
|
|
extern const uint16_t E131_DEFAULT_PORT;
|
|
extern const uint8_t E131_DEFAULT_PRIORITY;
|
|
|
|
/* E1.31 Socket Address Type */
|
|
typedef struct sockaddr_in e131_addr_t;
|
|
|
|
/* E1.31 Packet Type */
|
|
/* All packet contents shall be transmitted in network byte order (big endian) */
|
|
typedef union {
|
|
PACK(struct {
|
|
PACK(struct { /* ACN Root Layer: 38 bytes */
|
|
uint16_t preamble_size; /* Preamble Size */
|
|
uint16_t postamble_size; /* Post-amble Size */
|
|
uint8_t acn_pid[12]; /* ACN Packet Identifier */
|
|
uint16_t flength; /* Flags (high 4 bits) & Length (low 12 bits) */
|
|
uint32_t vector; /* Layer Vector */
|
|
uint8_t cid[16]; /* Component Identifier (UUID) */
|
|
}) root;
|
|
|
|
PACK(struct { /* Framing Layer: 77 bytes */
|
|
uint16_t flength; /* Flags (high 4 bits) & Length (low 12 bits) */
|
|
uint32_t vector; /* Layer Vector */
|
|
uint8_t source_name[64]; /* User Assigned Name of Source (UTF-8) */
|
|
uint8_t priority; /* Packet Priority (0-200, default 100) */
|
|
uint16_t reserved; /* Reserved (should be always 0) */
|
|
uint8_t seq_number; /* Sequence Number (detect duplicates or out of order packets) */
|
|
uint8_t options; /* Options Flags (bit 7: preview data, bit 6: stream terminated) */
|
|
uint16_t universe; /* DMX Universe Number */
|
|
}) frame;
|
|
|
|
PACK(struct { /* Device Management Protocol (DMP) Layer: 523 bytes */
|
|
uint16_t flength; /* Flags (high 4 bits) / Length (low 12 bits) */
|
|
uint8_t vector; /* Layer Vector */
|
|
uint8_t type; /* Address Type & Data Type */
|
|
uint16_t first_addr; /* First Property Address */
|
|
uint16_t addr_inc; /* Address Increment */
|
|
uint16_t prop_val_cnt; /* Property Value Count (1 + number of slots) */
|
|
uint8_t prop_val[513]; /* Property Values (DMX start code + slots data) */
|
|
}) dmp;
|
|
});
|
|
|
|
uint8_t raw[638]; /* raw buffer view: 638 bytes */
|
|
} e131_packet_t;
|
|
|
|
/* E1.31 Framing Options Type */
|
|
typedef enum {
|
|
E131_OPT_TERMINATED = 6,
|
|
E131_OPT_PREVIEW = 7,
|
|
} e131_option_t;
|
|
|
|
/* E1.31 Validation Errors Type */
|
|
typedef enum {
|
|
E131_ERR_NONE,
|
|
E131_ERR_NULLPTR,
|
|
E131_ERR_PREAMBLE_SIZE,
|
|
E131_ERR_POSTAMBLE_SIZE,
|
|
E131_ERR_ACN_PID,
|
|
E131_ERR_VECTOR_ROOT,
|
|
E131_ERR_VECTOR_FRAME,
|
|
E131_ERR_VECTOR_DMP,
|
|
E131_ERR_TYPE_DMP,
|
|
E131_ERR_FIRST_ADDR_DMP,
|
|
E131_ERR_ADDR_INC_DMP,
|
|
} e131_error_t;
|
|
|
|
/* Create a socket file descriptor suitable for E1.31 communication */
|
|
extern int e131_socket(void);
|
|
|
|
/* Bind a socket file descriptor to a port number for E1.31 communication */
|
|
extern int e131_bind(int sockfd, const uint16_t port);
|
|
|
|
/* Initialize a unicast E1.31 destination using a host and port number */
|
|
extern int e131_unicast_dest(e131_addr_t *dest, const char *host, const uint16_t port);
|
|
|
|
/* Initialize a multicast E1.31 destination using a universe and port number */
|
|
extern int e131_multicast_dest(e131_addr_t *dest, const uint16_t universe, const uint16_t port);
|
|
|
|
/* Describe an E1.31 destination into a string (must be at least 22 bytes) */
|
|
extern int e131_dest_str(char *str, const e131_addr_t *dest);
|
|
|
|
/* Join a socket file descriptor to an E1.31 multicast group using a universe */
|
|
extern int e131_multicast_join(int sockfd, const uint16_t universe);
|
|
|
|
/* Initialize an E1.31 packet using a universe and a number of slots */
|
|
extern int e131_pkt_init(e131_packet_t *packet, const uint16_t universe, const uint16_t num_slots);
|
|
|
|
/* Get the state of a framing option in an E1.31 packet */
|
|
extern bool e131_get_option(const e131_packet_t *packet, const e131_option_t option);
|
|
|
|
/* Set the state of a framing option in an E1.31 packet */
|
|
extern int e131_set_option(e131_packet_t *packet, const e131_option_t option, const bool state);
|
|
|
|
/* Send an E1.31 packet to a socket file descriptor using a destination */
|
|
extern ssize_t e131_send(int sockfd, const e131_packet_t *packet, const e131_addr_t *dest);
|
|
|
|
/* Receive an E1.31 packet from a socket file descriptor */
|
|
extern ssize_t e131_recv(int sockfd, e131_packet_t *packet);
|
|
|
|
/* Validate that an E1.31 packet is well-formed */
|
|
extern e131_error_t e131_pkt_validate(const e131_packet_t *packet);
|
|
|
|
/* Check if an E1.31 packet should be discarded (sequence number out of order) */
|
|
extern bool e131_pkt_discard(const e131_packet_t *packet, const uint8_t last_seq_number);
|
|
|
|
/* Dump an E1.31 packet to a stream (i.e. stdout, stderr) */
|
|
extern int e131_pkt_dump(FILE *stream, const e131_packet_t *packet);
|
|
|
|
/* Return a string describing an E1.31 error */
|
|
extern const char *e131_strerror(const e131_error_t error);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif
|