#include #include #include #include #include #include #include #include #include "logger.h" #include "fader.h" #include "udpproto.h" #define SET_COLOUR 0 #define FADE_COLOUR 1 #define ADD_COLOUR 2 #define SET_FADESTEP 3 int sock; int udpproto_init(uint16_t port) { struct sockaddr_in listen_addr; // initialize UDP server socket sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if(sock == -1) { LOG(LVL_ERR, "udpproto: Could not initialize UDP socket: %s.", strerror(errno)); return -1; } memset(&listen_addr, 0, sizeof(listen_addr)); listen_addr.sin_family = AF_INET; listen_addr.sin_port = htons(port); listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sock, (struct sockaddr*)&listen_addr, sizeof(listen_addr)) == -1) { LOG(LVL_ERR, "udpproto: Could not bind socket to port %i: %s.", port, strerror(errno)); return -1; } return 0; } int udpproto_process(void) { socklen_t remote_addr_len; struct sockaddr remote_addr; uint8_t pkgbuf[65536]; ssize_t rcvbytes, offset = 0; uint8_t r, g, b, w, action, module; int fds_ready; // check if there is data to be read (to prevent blocking) struct pollfd pfd = { .fd = sock, .events = POLLIN, .revents = 0 }; fds_ready = poll(&pfd, 1, 0); if(fds_ready == -1) { LOG(LVL_ERR, "udpproto: poll() failed: %s.", strerror(errno)); return -1; } else if(fds_ready == 0) { // there's nothing to be read return 0; } // receive the data remote_addr_len = sizeof(remote_addr); rcvbytes = recvfrom(sock, pkgbuf, 65536, 0, (struct sockaddr*)&remote_addr, &remote_addr_len); if(rcvbytes == -1) { LOG(LVL_ERR, "udpproto: recvfrom() failed: %s.", strerror(errno)); return -1; } pkgbuf[rcvbytes] = 0; // parse commands from packet offset = 0; while(offset <= rcvbytes - 5) { action = pkgbuf[offset + 0]; module = pkgbuf[offset + 1]; r = pkgbuf[offset + 2]; g = pkgbuf[offset + 3]; b = pkgbuf[offset + 4]; w = pkgbuf[offset + 5]; offset += 5; switch(action) { case SET_COLOUR: fader_set_colour(module, r, g, b, w); break; case FADE_COLOUR: fader_fade_colour(module, r, g, b, w); break; case ADD_COLOUR: fader_add_colour(module, r, g, b, w); break; case SET_FADESTEP: fader_set_fadestep(r); // red channel contains the fadestep in this case break; default: LOG(LVL_DEBUG, "udpproto: Action %u not implemented yet.", action); } } return rcvbytes / 6; // number of commands in packet } void udpproto_shutdown(void) { close(sock); }