diff --git a/artnet/artnet.c b/artnet/artnet.c index fc016ad..53e69d2 100644 --- a/artnet/artnet.c +++ b/artnet/artnet.c @@ -64,7 +64,7 @@ uint16_t LOW_BYTE = 0x00FF; uint16_t HIGH_BYTE = 0xFF00; void copy_apr_to_node_entry(artnet_node_entry e, artnet_reply_t *reply); -int find_nodes_from_uni(node_list_t *nl, uint8_t uni, SI *ips, int size); +int find_nodes_from_uni(node_list_t *nl, uint16_t uni, SI *ips, int size); /* * Creates a new ArtNet node. @@ -739,7 +739,7 @@ int artnet_send_address(artnet_node vn, const char *longName, uint8_t inAddr[ARTNET_MAX_PORTS], uint8_t outAddr[ARTNET_MAX_PORTS], - uint8_t subAddr, artnet_port_command_t cmd) { + uint8_t net, uint8_t subAddr, artnet_port_command_t cmd) { node n = (node) vn; artnet_packet_t p; node_entry_private_t *ent = find_private_entry(n,e); @@ -763,7 +763,6 @@ int artnet_send_address(artnet_node vn, p.data.addr.opCode = htols(ARTNET_ADDRESS); p.data.addr.verH = 0; p.data.addr.ver = ARTNET_VERSION; - p.data.addr.filler1 = 0; p.data.addr.filler2 = 0; strncpy((char*) &p.data.addr.shortname, shortName, ARTNET_SHORT_NAME_LENGTH); strncpy((char*) &p.data.addr.longname, longName, ARTNET_LONG_NAME_LENGTH); @@ -771,6 +770,7 @@ int artnet_send_address(artnet_node vn, memcpy(&p.data.addr.swin, inAddr, ARTNET_MAX_PORTS); memcpy(&p.data.addr.swout, outAddr, ARTNET_MAX_PORTS); + p.data.addr.net = net; p.data.addr.subnet = subAddr; p.data.addr.swvideo = 0x00; p.data.addr.command = cmd; @@ -1128,27 +1128,30 @@ int artnet_set_node_type(artnet_node vn, artnet_node_type type) { * Note that changing the subnet address will cause the universe addresses of all ports to change. * * @param vn the artnet_node + * @param net new net address * @param subnet new subnet address */ -int artnet_set_subnet_addr(artnet_node vn, uint8_t subnet) { +int artnet_set_net_subnet_addr(artnet_node vn, uint8_t net, uint8_t subnet) { node n = (node) vn; int i, ret; check_nullnode(vn); + n->state.default_net = net; n->state.default_subnet = subnet; // if not under network control, and the subnet is different from the current one - if (!n->state.subnet_net_ctl && subnet != n->state.subnet) { + if (!n->state.subnet_net_ctl && (subnet != n->state.subnet || net != n->state.net)) { + n->state.net = net; n->state.subnet = subnet; // redo the addresses for each port for (i =0; i < ARTNET_MAX_PORTS; i++) { - n->ports.in[i].port_addr = ((n->state.subnet & LOW_NIBBLE) << 4) | (n->ports.in[i].port_addr & LOW_NIBBLE); + n->ports.in[i].port_addr = (net << 8) | ((n->state.subnet & LOW_NIBBLE) << 4) | (n->ports.in[i].port_addr & LOW_NIBBLE); // reset dmx sequence number n->ports.in[i].seq = 0; - n->ports.out[i].port_addr = ((n->state.subnet & LOW_NIBBLE) << 4) | (n->ports.out[i].port_addr & LOW_NIBBLE); + n->ports.out[i].port_addr = (net << 8) | ((n->state.subnet & LOW_NIBBLE) << 4) | (n->ports.out[i].port_addr & LOW_NIBBLE); } if (n->state.mode == ARTNET_ON) { @@ -1290,7 +1293,7 @@ int artnet_set_port_addr(artnet_node vn, // if not under network control and address is changing if (!port->net_ctl && (changed || (addr & LOW_NIBBLE) != (port->addr & LOW_NIBBLE))) { - port->addr = ((n->state.subnet & LOW_NIBBLE) << 4) | (addr & LOW_NIBBLE); + port->addr = n->state.net << 8 | ((n->state.subnet & LOW_NIBBLE) << 4) | (addr & LOW_NIBBLE); // reset seq if input port if (dir == ARTNET_INPUT_PORT) @@ -1345,6 +1348,7 @@ int artnet_get_config(artnet_node vn, artnet_node_config_t *config) { strncpy(config->short_name, n->state.short_name, ARTNET_SHORT_NAME_LENGTH); strncpy(config->long_name, n->state.long_name, ARTNET_LONG_NAME_LENGTH); + config->net = n->state.net; config->subnet = n->state.subnet; for (i = 0; i < ARTNET_MAX_PORTS; i++) { @@ -1561,15 +1565,17 @@ node_entry_private_t *find_entry_from_ip(node_list_t *nl, SI ip) { * @param size size of ips * @return number of nodes matched */ -int find_nodes_from_uni(node_list_t *nl, uint8_t uni, SI *ips, int size) { +int find_nodes_from_uni(node_list_t *nl, uint16_t uni, SI *ips, int size) { node_entry_private_t *tmp; int count = 0; int i,j = 0; + uint16_t outputUniverse = 0; for (tmp = nl->first; tmp; tmp = tmp->next) { int added = FALSE; for (i =0; i < tmp->pub.numbports; i++) { - if (tmp->pub.swout[i] == uni && ips) { + outputUniverse = (tmp->pub.swout[i] & LOW_NIBBLE) | tmp->pub.sub << 4 | tmp->pub.net << 8; + if (outputUniverse == uni && ips) { if (j < size && !added) { ips[j++] = tmp->ip; added = TRUE; @@ -1590,7 +1596,8 @@ void copy_apr_to_node_entry(artnet_node_entry e, artnet_reply_t *reply) { // the ip is network byte ordered memcpy(&e->ip, &reply->ip, 4); e->ver = bytes_to_short(reply->verH, reply->ver); - e->sub = bytes_to_short(reply->subH, reply->sub); + e->net = reply->net; + e->sub = reply->sub; e->oem = bytes_to_short(reply->oemH, reply->oem); e->ubea = reply->ubea; memcpy(&e->etsaman, &reply->etsaman, 2); diff --git a/artnet/artnet.h b/artnet/artnet.h index 2b79134..7dc04b6 100644 --- a/artnet/artnet.h +++ b/artnet/artnet.h @@ -171,7 +171,8 @@ typedef enum { typedef struct artnet_node_entry_s { uint8_t ip[ARTNET_IP_SIZE]; /**< The IP address, Network byte ordered*/ int16_t ver; /**< The firmware version */ - int16_t sub; /**< The subnet address */ + int8_t net; /**< The net address */ + int8_t sub; /**< The subnet address */ int16_t oem; /**< The OEM value */ uint8_t ubea; /**< The UBEA version */ uint8_t status; @@ -198,6 +199,7 @@ typedef artnet_node_entry_t *artnet_node_entry; typedef struct { char short_name[ARTNET_SHORT_NAME_LENGTH]; char long_name[ARTNET_LONG_NAME_LENGTH]; + uint8_t net; uint8_t subnet; uint8_t in_ports[ARTNET_MAX_PORTS]; uint8_t out_ports[ARTNET_MAX_PORTS]; @@ -272,6 +274,7 @@ EXTERN int artnet_send_address(artnet_node n, const char *longName, uint8_t inAddr[ARTNET_MAX_PORTS], uint8_t outAddr[ARTNET_MAX_PORTS], + uint8_t net, uint8_t subAddr, artnet_port_command_t cmd); EXTERN int artnet_send_input(artnet_node n, @@ -326,7 +329,7 @@ EXTERN int artnet_set_port_addr(artnet_node n, int id, artnet_port_dir_t dir, uint8_t addr); -EXTERN int artnet_set_subnet_addr(artnet_node n, uint8_t subnet); +EXTERN int artnet_set_net_subnet_addr(artnet_node n, uint8_t net, uint8_t subnet); EXTERN int artnet_get_universe_addr(artnet_node n, int id, artnet_port_dir_t dir); diff --git a/artnet/packets.h b/artnet/packets.h index d55e1e1..f34675f 100644 --- a/artnet/packets.h +++ b/artnet/packets.h @@ -96,7 +96,7 @@ struct artnet_reply_s { uint16_t port; uint8_t verH; uint8_t ver; - uint8_t subH; + uint8_t net; uint8_t sub; uint8_t oemH; uint8_t oem; @@ -195,7 +195,7 @@ struct artnet_address_s { uint16_t opCode; uint8_t verH; uint8_t ver; - uint8_t filler1; + uint8_t net; uint8_t filler2; uint8_t shortname[ARTNET_SHORT_NAME_LENGTH]; uint8_t longname[ARTNET_LONG_NAME_LENGTH]; @@ -254,7 +254,7 @@ struct artnet_todrequest_s { uint8_t spare5; uint8_t spare6; uint8_t spare7; - uint8_t spare8; + uint8_t net; uint8_t command; uint8_t adCount; uint8_t address[ARTNET_MAX_RDM_ADCOUNT]; @@ -278,7 +278,7 @@ struct artnet_toddata_s { uint8_t spare5; uint8_t spare6; uint8_t spare7; - uint8_t spare8; + uint8_t net; uint8_t cmdRes; uint8_t address; uint8_t uidTotalHi; diff --git a/artnet/private.h b/artnet/private.h index cc1be11..f35e225 100644 --- a/artnet/private.h +++ b/artnet/private.h @@ -282,7 +282,7 @@ typedef struct { // first a generic port typedef struct { - uint8_t addr; // the port address + uint16_t addr; // the port address uint8_t default_addr; // the address set by the hardware uint8_t net_ctl; // if the port address is under network control uint8_t status; // status of the port @@ -417,6 +417,7 @@ typedef struct { SI ip_addr; SI bcast_addr; uint8_t hw_addr[ARTNET_MAC_SIZE]; + uint8_t default_net; uint8_t default_subnet; uint8_t subnet_net_ctl; int send_apr_on_change; @@ -425,6 +426,7 @@ typedef struct { char short_name[ARTNET_SHORT_NAME_LENGTH]; char long_name[ARTNET_LONG_NAME_LENGTH]; char report[ARTNET_REPORT_LENGTH]; + uint8_t net; uint8_t subnet; uint8_t oem_hi; uint8_t oem_lo; diff --git a/artnet/receive.c b/artnet/receive.c index eb87137..daa1956 100644 --- a/artnet/receive.c +++ b/artnet/receive.c @@ -20,7 +20,7 @@ #include "private.h" -uint8_t _make_addr(uint8_t subnet, uint8_t addr); +uint16_t _make_addr(uint8_t net, uint8_t subnet, uint8_t addr); void check_merge_timeouts(node n, int port); void merge(node n, int port, int length, uint8_t *latest); @@ -238,7 +238,7 @@ void handle_dmx(node n, artnet_packet p) { * */ int handle_address(node n, artnet_packet p) { - int i, old_subnet; + int i, old_subnet, old_net; int addr[ARTNET_MAX_PORTS]; int ret; @@ -269,9 +269,11 @@ int handle_address(node n, artnet_packet p) { } // program subnet + old_net = p->data.addr.net; old_subnet = p->data.addr.subnet; if (p->data.addr.subnet == PROGRAM_DEFAULTS) { // reset to defaults + n->state.net = n->state.default_net; n->state.subnet = n->state.default_subnet; n->state.subnet_net_ctl = FALSE; @@ -281,11 +283,11 @@ int handle_address(node n, artnet_packet p) { } // check if subnet has actually changed - if (old_subnet != n->state.subnet) { + if (old_net != n->state.net || old_subnet != n->state.subnet) { // if it does we need to change all port addresses for(i=0; i< ARTNET_MAX_PORTS; i++) { - n->ports.in[i].port_addr = _make_addr(n->state.subnet, n->ports.in[i].port_addr); - n->ports.out[i].port_addr = _make_addr(n->state.subnet, n->ports.out[i].port_addr); + n->ports.in[i].port_addr = _make_addr(n->state.net, n->state.subnet, (uint8_t)n->ports.in[i].port_addr); + n->ports.out[i].port_addr = _make_addr(n->state.net, n->state.subnet, (uint8_t)n->ports.out[i].port_addr); } } @@ -295,11 +297,11 @@ int handle_address(node n, artnet_packet p) { continue; } else if (p->data.addr.swin[i] == PROGRAM_DEFAULTS) { // reset to defaults - n->ports.in[i].port_addr = _make_addr(n->state.subnet, n->ports.in[i].port_default_addr); + n->ports.in[i].port_addr = _make_addr(n->state.net, n->state.subnet, n->ports.in[i].port_default_addr); n->ports.in[i].port_net_ctl = FALSE; } else if ( p->data.addr.swin[i] & PROGRAM_CHANGE_MASK) { - n->ports.in[i].port_addr = _make_addr(n->state.subnet, p->data.addr.swin[i]); + n->ports.in[i].port_addr = _make_addr(n->state.net, n->state.subnet, p->data.addr.swin[i]); n->ports.in[i].port_net_ctl = TRUE; } } @@ -310,11 +312,11 @@ int handle_address(node n, artnet_packet p) { continue; } else if (p->data.addr.swout[i] == PROGRAM_DEFAULTS) { // reset to defaults - n->ports.out[i].port_addr = _make_addr(n->state.subnet, n->ports.out[i].port_default_addr); + n->ports.out[i].port_addr = _make_addr(n->state.net, n->state.subnet, n->ports.out[i].port_default_addr); n->ports.out[i].port_net_ctl = FALSE; n->ports.out[i].port_enabled = TRUE; } else if ( p->data.addr.swout[i] & PROGRAM_CHANGE_MASK) { - n->ports.out[i].port_addr = _make_addr(n->state.subnet, p->data.addr.swout[i]); + n->ports.out[i].port_addr = _make_addr(n->state.net, n->state.subnet, p->data.addr.swout[i]); n->ports.in[i].port_net_ctl = TRUE; n->ports.out[i].port_enabled = TRUE; } @@ -854,10 +856,10 @@ int16_t get_type(artnet_packet p) { /* - * takes a subnet and an address and creates the universe address + * takes a net, subnet and an address and creates the universe address */ -uint8_t _make_addr(uint8_t subnet, uint8_t addr) { - return ((subnet & LOW_NIBBLE) << 4) | (addr & LOW_NIBBLE); +uint16_t _make_addr(uint8_t net, uint8_t subnet, uint8_t addr) { + return (net << 8 ) | ((subnet & LOW_NIBBLE) << 4) | (addr & LOW_NIBBLE); } diff --git a/artnet/transmit.c b/artnet/transmit.c index ce19b11..efdd7c9 100644 --- a/artnet/transmit.c +++ b/artnet/transmit.c @@ -116,9 +116,10 @@ int artnet_tx_tod_request(node n) { todreq.data.todreq.adCount = 0; // include all enabled ports + todreq.data.todreq.net = n->state.net; for (i=0; i < ARTNET_MAX_PORTS; i++) { if (n->ports.out[i].port_enabled) { - todreq.data.todreq.address[todreq.data.todreq.adCount++] = n->ports.out[i].port_addr; + todreq.data.todreq.address[todreq.data.todreq.adCount++] = n->ports.out[i].port_addr & LOW_BYTE; } } @@ -155,7 +156,7 @@ int artnet_tx_tod_data(node n, int id) { // codes aren't given. The windows drivers don't have these either.... tod.data.toddata.cmdRes = ARTNET_TOD_FULL; - tod.data.toddata.address = n->ports.out[id].port_addr; + tod.data.toddata.address = n->ports.out[id].port_addr & LOW_BYTE; tod.data.toddata.uidTotalHi = short_get_high_byte(n->ports.out[id].port_tod.length); tod.data.toddata.uidTotal = short_get_low_byte(n->ports.out[id].port_tod.length); @@ -368,7 +369,7 @@ int artnet_tx_build_art_poll_reply(node n) { ar->port = htols(ARTNET_PORT); ar->verH = 0; ar->ver = 0; - ar->subH = 0; + ar->net = n->state.net; ar->sub = n->state.subnet; ar->oemH = n->state.oem_hi; ar->oem = n->state.oem_lo; @@ -404,8 +405,8 @@ int artnet_tx_build_art_poll_reply(node n) { ar->porttypes[i] = n->ports.types[i]; ar->goodinput[i] = n->ports.in[i].port_status; ar->goodoutput[i] = n->ports.out[i].port_status; - ar->swin[i] = n->ports.in[i].port_addr; - ar->swout[i] = n->ports.out[i].port_addr; + ar->swin[i] = n->ports.in[i].port_addr & LOW_NIBBLE; + ar->swout[i] = n->ports.out[i].port_addr & LOW_NIBBLE; } ar->swvideo = 0;