Beispiel #1
0
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;
}
Beispiel #2
0
/* 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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
/* 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;
    }