EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: Problems sending \x0 with devGpib driver
From: Eric Norum <[email protected]>
To: "[email protected] talk" <[email protected]>
Date: Thu, 8 Nov 2012 09:02:25 -0800
Although not directly related to this thread, an issue I've encountered when attempting to write StreamDevice support for devices with "esoteric" command/reply formats is the inability to provide a custom conversion routine as provided by devGpib.   

I went digging through my (very) old e-mail messages and recovered this one proposing an addition to StreamDevice that would allow for user-supplied conversion code.  It's still not quite as general a solution as that provided by the devGpib GPIBCVTIO support but it does allow for message format conversions beyond those provided by StreamDevice.

Perhaps others might find this useful enough that it could be made part of the StreamDevice distribution.

===============================================================================
New format string modifier <function_name>.  For example,
     %<function_name>ld
     %<function_name>f
     %<function_name>lf

Where function_name is the name of a conversion function with prototype:
int func (char *msgBuf, int msgLen, dbCommon *record, format_t *format, void *value);
Arguments:
     msgBuf - Pointer to next character to be consumed or stored.
     msgLen - Remaining characters in input message or space in output buffer.
     record - EPICS record being read/written.
     format - Pointer to streams format structure.
     value  - Pointer to value to be converted.
Return Value:
     Number of bytes consumed/produced by the conversion function.
     -1 on error (I/O mismatch, not enough space in output buffer, etc.)

===============================================================================
Here's an example function to perform a conversion not possible by any existing
streams conversion format character.  This is for a video multiplexor with a
particularly horrible command set.
/*
  * Custom conversion routine
  * Handle messages of the form:
  *           ....SL0O#T( )
  *           ....SL0O#T( # )
  */
static int
autoPatchConversion (char *msgBuf, int msgLen, dbCommon *record, format_t *format, void *value)
{
     int len;
     int match;
     int chan;
     long ltmp;
     char *cp;

     if ((format->type != DBF_LONG)
      || (format->conversion != 'd'))
         return -1;

     /*
      * Find the last 'S' in the message
      */
     cp = msgBuf + msgLen;
     for (;;) {
         if (cp == msgBuf)
             return -1;
         if (*--cp == 'S')
             break;
     }

     /*
      * Parse the message
      */
     if (((match = sscanf(cp,"SL0O%dT( %ld )%n", &chan, &ltmp, &len)) == 2)
      || ((match = sscanf(cp,"SL0O%dT( )%n", &chan, &len)) == 1)) {
         /* Could put check here that 'chan' matches record */
         *(long *)value = (match == 2) ? ltmp : 0;
         return len + (cp - msgBuf);
     }
     return -1;
}

/* Called by registerRecordDeviceDriver */
void autoPatchRegistrar (void)
{
     streamFormatCalloutAdd("autoPatch", autoPatchConversion)
}


===============================================================================
Here are the changes I made to implement this.  As you can see, they're pretty
small but I think they do most of the job.

diff -ubrN orig/streamDeviceApp/src/devStream.c 
libStream/streamDevice/src/devStream.c
--- orig/streamDeviceApp/src/devStream.c        2003-01-31 
04:23:40.000000000 -0600
+++ libStream/streamDevice/src/devStream.c      2003-02-14 
15:34:54.000000000 -0600
@@ -554,6 +554,13 @@
      unsigned char bcd1, bcd10;
      int status;

+    if (format->flags & FORMAT_FLAG_CALLOUT) {
+        StreamFormatCallout callout;
+        memcpy(&callout, format->callout, sizeof callout);
+        len = (*callout)(source, stream->length-stream->processed, 
record, format, value);
+    }
+    else
+    {
      switch (format->conversion)
      {
          case 'd':
@@ -782,6 +789,7 @@
              stream->status = SOFT_ALARM;
              return ERROR;
      }
+    }
      if (len < 0)
      {
          stream->status = CALC_ALARM;
diff -ubrN orig/streamDeviceApp/src/devStreamFormatCalloutRegistry.c 
libStream/streamDevice/src/devStreamFormatCalloutRegistry.c
--- orig/streamDeviceApp/src/devStreamFormatCalloutRegistry.c 1969-12-31 18:00:00.000000000 -0600
+++ libStream/streamDevice/src/devStreamFormatCalloutRegistry.c 2003-02-14 14:44:33.000000000 -0600
@@ -0,0 +1,18 @@
+#include <registry.h>
+#include "devStreamProtocol.h"
+
+static const char *streamFormatCalloutRegistry = 
"streamFormatCalloutRegistry";
+static void *registryID = (void *)&streamFormatCalloutRegistry;
+
+int
+streamFormatCalloutAdd(const char *name, StreamFormatCallout callout)
+{
+    return registryAdd(registryID, name, (void *)callout);
+}
+
+StreamFormatCallout
+streamFormatCalloutFind(const char *name)
+{
+    return (StreamFormatCallout)registryFind(registryID, name);
+}
+
diff -ubrN orig/streamDeviceApp/src/devStreamProtocol.c 
libStream/streamDevice/src/devStreamProtocol.c
--- orig/streamDeviceApp/src/devStreamProtocol.c        2003-01-31 02:50:31.000000000 -0600
+++ libStream/streamDevice/src/devStreamProtocol.c      2003-02-14 14:41:49.000000000 -0600
@@ -628,6 +628,22 @@
              case '*':
                  format->flags |= FORMAT_FLAG_SKIP;
                  break;
+            case '<':
+                {
+                StreamFormatCallout callout;
+                char *functionName = ++ptr;
+                ptr = strchr(ptr, '>');
+                if (ptr == NULL)
+                    return ERROR;
+                *ptr = '\0';
+                callout = (int(*)())streamFormatCalloutFind(functionName);
+                memcpy(format->callout, &callout, sizeof callout);
+                *ptr = '>';
+                if (format->callout == NULL)
+                    return ERROR;
+                format->flags |= FORMAT_FLAG_CALLOUT;
+                }
+                break;
              default:
                  loop = 0;
          }
@@ -639,7 +655,8 @@
      /* optional precision */
      if (*ptr == '.')
      {
-        size = strtol(++ptr, &ptr, 10);
+        ptr++;
+        size = strtol(ptr, &ptr, 10);
          if (size >= 128) return ERROR;
          format->prec = size;
      }
diff -ubrN orig/streamDeviceApp/src/devStreamProtocol.h 
libStream/streamDevice/src/devStreamProtocol.h
--- orig/streamDeviceApp/src/devStreamProtocol.h        2003-01-29 10:29:22.000000000 -0600
+++ libStream/streamDevice/src/devStreamProtocol.h      2003-02-14 15:33:27.000000000 -0600
@@ -29,6 +29,7 @@
  #define FORMAT_FLAG_ALT   (0x08)
  #define FORMAT_FLAG_ZERO  (0x10)
  #define FORMAT_FLAG_SKIP  (0x20)
+#define FORMAT_FLAG_CALLOUT (0x40)

  typedef struct {
      unsigned short bufferSize;
@@ -50,9 +51,15 @@
      char flags;
      signed char prec;
      unsigned char width;
+    char callout[sizeof(int(*)())];
      char string [1];
  } format_t;

+struct dbCommon;
+typedef int (*StreamFormatCallout)(char *msgBuf, int msgLen, struct dbCommon *record, format_t *format, void *value);
+int streamFormatCalloutAdd(const char *name, StreamFormatCallout);
+StreamFormatCallout streamFormatCalloutFind(const char *name);
+
  /*****************************************
  * parseProtocol
  *


On Nov 8, 2012, at 5:50 AM, Dirk Zimoch <[email protected]> wrote:

> …….
> Yes.
> 
> The problem is writeMsgString(gpibDpvt *pgpibDpvt,const char *str) from devGpib/devSupportGpib.c which does not have any length parameter.
> 
> The lower level asynOctet function write() as well as all implementations I have seen have (and use) a length parameter. StreamDevice uses this function and passes the correct length.
> 
> Do not use devGpib for any new project!
> 

-- 
Eric Norum
[email protected]






Replies:
Re: Problems sending \x0 with devGpib driver Dirk Zimoch
References:
Problems sending \x0 with devGpib driver Andrew Wagner
Re: Problems sending \x0 with devGpib driver Eric Norum
Re: Problems sending \x0 with devGpib driver Andrew Wagner
Re: Problems sending \x0 with devGpib driver Eric Norum
Re: Problems sending \x0 with devGpib driver Dirk Zimoch

Navigate by Date:
Prev: EPICS Position Available careers
Next: compile EPICS base on Mac OS (Snow Leopard) using GCC from macport Shen, Guobao
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: Problems sending \x0 with devGpib driver Dirk Zimoch
Next: Re: Problems sending \x0 with devGpib driver Dirk Zimoch
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 18 Nov 2013 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·