static TagInfo *new_TagInfo(const char *string_tag, size_t elements) { TagInfo *info = (TagInfo *) calloc(sizeof(TagInfo), 1); if (!info) return 0; info->string_tag = EIP_strdup(string_tag); if (! info->string_tag) return 0; info->tag = EIP_parse_tag(string_tag); if (! info->tag) { EIP_printf(2, "new_TagInfo: failed to parse tag '%s'\n", string_tag); return 0; } info->elements = elements; info->data_lock = epicsMutexCreate(); if (! info->data_lock) { EIP_printf(0, "new_TagInfo (%s): Cannot create data lock\n", string_tag); return 0; } DLL_init(&info->callbacks); return info; }
/* Create a PLC entry: * name : identifier * ip_address: DNS name or dot-notation */ eip_bool drvEtherIP_define_PLC(const char *PLC_name, const char *ip_addr, int slot) { PLC *plc; epicsMutexLock(drvEtherIP_private.lock); plc = get_PLC(PLC_name, true); if (plc) { if (plc->ip_addr) { EIP_printf(1, "Redefining IP address of PLC %s?\n", PLC_name); free(plc->ip_addr); } plc->ip_addr = EIP_strdup(ip_addr); plc->slot = slot; } epicsMutexUnlock(drvEtherIP_private.lock); return plc && plc->ip_addr; }
static PLC *new_PLC(const char *name) { PLC *plc = (PLC *) calloc(1, sizeof(PLC)); if (! plc) return 0; plc->name = EIP_strdup(name); if (! plc->name) return 0; DLL_init (&plc->scanlists); plc->lock = epicsMutexCreate(); if (! plc->lock) { EIP_printf (0, "new_PLC (%s): Cannot create mutex\n", name); return 0; } plc->connection = EIP_init(); if (! plc->connection) { EIP_printf (0, "new_PLC (%s): EIP_init failed\n", name); return 0; } return plc; }
/* This driver uses INST_IO links, * the string has to be of the format * * @PLC tag flags * * count: number of array elements to read (only != 1 for waveform record) * bits: if >0 indicates that we want binary data, * then it's the number of bits */ static long analyze_link(dbCommon *rec, EIPCallback cbtype, const DBLINK *link, size_t count, size_t bits) { DevicePrivate *pvt = (DevicePrivate *)rec->dpvt; char *p, *end; size_t i, tag_len, last_element, bit=0; unsigned long mask; double period = 0.0; eip_bool single_element = false; SpecialOptions special = 0; if (! EIP_strdup(&pvt->link_text, link->value.instio.string, strlen (link->value.instio.string))) { errlogPrintf("devEtherIP (%s): Cannot copy link\n", rec->name); return S_dev_noMemory; } /* Find PLC */ p = find_token(pvt->link_text, &end); if (! p) { errlogPrintf("devEtherIP (%s): Missing PLC in link '%s'\n", rec->name, pvt->link_text); return S_db_badField; } if (! EIP_strdup(&pvt->PLC_name, p, end-p)) { errlogPrintf("devEtherIP (%s): Cannot copy PLC\n", rec->name); return S_dev_noMemory; } /* Find Tag */ p = find_token(end, &end); if (! p) { errlogPrintf("devEtherIP (%s): Missing tag in link '%s'\n", rec->name, pvt->link_text); return(S_db_badField); } tag_len = end-p; if (! EIP_strdup(&pvt->string_tag, p, tag_len)) { errlogPrintf("devEtherIP (%s): Cannot copy tag\n", rec->name); return S_dev_noMemory; } /* Check for more flags */ while ((p = find_token(end, &end))) { for (i=0, mask=1; mask < SPCO_INVALID; ++i, mask=mask<<1) { if (strncmp(p, special_options[i].text, special_options[i].len) == 0) { special |= mask; if (mask==SPCO_READ_SINGLE_ELEMENT) { if (count != 1) { errlogPrintf("devEtherIP (%s): " "Array record cannot use 'E' flag " "('%s')\n", rec->name, pvt->link_text); return S_db_badField; } single_element = true; } else if (mask==SPCO_SCAN_PERIOD) { period = strtod(p+2, &end); if (end==p || period==HUGE_VAL || period==-HUGE_VAL) { errlogPrintf("devEtherIP (%s): " "Error in scan flag in link '%s'\n", rec->name, pvt->link_text); return S_db_badField; } } else if (mask==SPCO_BIT) { bit = strtod(p+2, &end); if (end==p || period==HUGE_VAL || period==-HUGE_VAL) { errlogPrintf("devEtherIP (%s): " "Error in bit flag in link '%s'\n", rec->name, pvt->link_text); return S_db_badField; } } break; } } if (mask >= SPCO_INVALID) { errlogPrintf("devEtherIP (%s): Invalid flag '%s' in link '%s'\n", rec->name, p, pvt->link_text); return S_db_badField; } } pvt->special = special; if (period <= 0.0) /* no scan flag-> get SCAN field: */ { period = get_period(rec); if (period <= 0) period = drvEtherIP_default_rate; if (period <= 0) { errlogPrintf("devEtherIP (%s): cannot decode SCAN field," " no scan flag given\n", rec->name); period = 1.0; /* default scan rate */ errlogPrintf("Device support will use the default of %g secs, ", period); errlogPrintf("please complete the record configuration\n"); } } /* Parsed link_text into PLC_name, string_tag, special flags. * Analyse further */ pvt->element = 0; p = &pvt->string_tag[tag_len-1]; if (*p == ']') /* array tag? */ { if (! single_element) { /* Cut "array_tag[el]" into "array_tag" + el */ while (p > pvt->string_tag) if (*(--p) == '[') break; if (p <= pvt->string_tag) { errlogPrintf("devEtherIP (%s): malformed array tag in '%s'\n", rec->name, pvt->link_text); return S_db_badField; } /* read element number */ pvt->element = strtol(p+1, &end, 0); if (end==p+1 || pvt->element==LONG_MAX || pvt->element==LONG_MIN) { errlogPrintf("devEtherIP (%s): malformed array tag in '%s'\n", rec->name, pvt->link_text); return S_db_badField; } /* remove element number text from tag */ *p = '\0'; } } pvt->plc = drvEtherIP_find_PLC(pvt->PLC_name); if (! pvt->plc) { errlogPrintf("devEtherIP (%s): unknown PLC '%s'\n", rec->name, pvt->PLC_name); return S_db_badField; } if (count > 1 && (bits > 0 || (special & SPCO_BIT))) { errlogPrintf("devEtherIP (%s): cannot access bits for array records\n", rec->name); return S_db_badField; } /* For Element==0 the following makes no difference, only * for binary records (bits=1 or more) * Options: * a) assume BOOL array (default) * b) non-BOOL, SPCO_BIT selected a bit in INT, DINT, ... */ if (bits>0 && !(special & SPCO_BIT)) { /* For element>0, assume that it's a BOOL array, * so the data is packed into UDINTs (CIP "BITS"). * The actual element requested is the UDINT index, * not the bit#. * Pick the bits within the UDINT via the mask. */ pvt->mask = 1U << (pvt->element & 0x1F); /* 0x1F == 31 */ last_element = pvt->element + bits - 1; pvt->element >>= 5; last_element >>= 5; }