Fix comedi_get_cmd_* so that commands are only generated once.
authorDavid Schleef <ds@schleef.org>
Sun, 15 Jul 2001 22:46:02 +0000 (22:46 +0000)
committerDavid Schleef <ds@schleef.org>
Sun, 15 Jul 2001 22:46:02 +0000 (22:46 +0000)
More error messages.

lib/buffer.c
lib/cmd.c
lib/comedi.c
lib/comedi_errno.h
lib/error.c
lib/libinternal.h

index 04e80cb70e3af5c806a256d0eafabc8df58d9381..ef1ff91b35f64eab002babc33b89bb103cfc466d 100644 (file)
@@ -11,6 +11,7 @@ int comedi_set_buffer_size(comedi_t *it, unsigned int subdev, unsigned int size)
        bc.subdevice = subdev;
        bc.size = size;
        ret = ioctl_bufconfig(it->fd, &bc);
+       __comedi_errno = errno;
        if(ret < 0) return ret;
 
        return bc.size;
@@ -25,6 +26,7 @@ int comedi_set_max_buffer_size(comedi_t *it, unsigned int subdev, unsigned int m
        bc.subdevice = subdev;
        bc.maximum_size = max_size;
        ret = ioctl_bufconfig(it->fd, &bc);
+       __comedi_errno = errno;
        if(ret < 0) return ret;
 
        return bc.maximum_size;
@@ -53,7 +55,8 @@ int comedi_mark_buffer_read(comedi_t *it, unsigned int subdev, unsigned int byte
        memset(&bi, 0, sizeof(bi));
        bi.bytes_read = bytes;
        ret = ioctl_bufinfo(it->fd, &bi);
-       if(ret < 0) return ret;
+       __comedi_errno = errno;
+       if(__comedi_errno == EINVAL)__comedi_errno = EBUF_OVR;
        return bi.buf_int_count - bi.buf_user_count;
 }
 
@@ -67,3 +70,15 @@ int comedi_get_buffer_offset(comedi_t *it, unsigned int subdev)
        if(ret < 0) return ret;
        return bi.buf_user_ptr;
 }
+
+int comedi_get_front_count(comedi_t *it, unsigned int subdev)
+{
+       int ret;
+       comedi_bufinfo bi;
+
+       memset(&bi, 0, sizeof(bi));
+       ret = ioctl_bufinfo(it->fd, &bi);
+       if(ret < 0) return ret;
+       return bi.buf_int_count;
+}
+
index 676334e3ba3fbfc85860a1aa7c49d6947bb8f9a0..44a42919bf3b1ea3ffc343aca0fd67d023cbf0a4 100644 (file)
--- a/lib/cmd.c
+++ b/lib/cmd.c
 #include <sys/time.h>
 #include <string.h>
 
+#include <libinternal.h>
 
-int comedi_get_cmd_src_mask(comedi_t *it,unsigned int s,comedi_cmd *cmd)
+
+int comedi_get_cmd_src_mask(comedi_t *it,unsigned int subd,comedi_cmd *cmd)
 {
-       memset(cmd,0,sizeof(*cmd));
+       subdevice *s;
+       int ret;
 
-       cmd->subdev = s;
+       if(!valid_subd(it,subd))return -1;
 
-       cmd->flags = 0;
+       s=it->subdevices+subd;
 
-       cmd->start_src = TRIG_ANY;
-       cmd->scan_begin_src = TRIG_ANY;
-       cmd->convert_src = TRIG_ANY;
-       cmd->scan_end_src = TRIG_ANY;
-       cmd->stop_src = TRIG_ANY;
+       if(s->cmd_mask_errno){
+               errno = s->cmd_mask_errno;
+               return -1;
+       }
 
-       return comedi_command_test(it,cmd);
-}
+       if(!s->cmd_mask){
+               comedi_cmd *mask;
+
+               mask = malloc(sizeof(comedi_cmd));
+
+               memset(mask,0,sizeof(*cmd));
 
+               mask->subdev = subd;
+               mask->flags = 0;
+               mask->start_src = TRIG_ANY;
+               mask->scan_begin_src = TRIG_ANY;
+               mask->convert_src = TRIG_ANY;
+               mask->scan_end_src = TRIG_ANY;
+               mask->stop_src = TRIG_ANY;
 
-int comedi_get_cmd_generic_timed(comedi_t *it,unsigned int s,comedi_cmd *cmd)
+               s->cmd_mask = mask;
+
+               ret = comedi_command_test(it,mask);
+               if(ret<0){
+                       s->cmd_mask_errno = errno;
+                       return -1;
+               }
+       }
+       *cmd=*s->cmd_mask;
+       return 0;
+}
+
+static int __generic_timed(comedi_t *it,unsigned int s,
+       comedi_cmd *cmd, unsigned int ns)
 {
        int ret;
 
        ret = comedi_get_cmd_src_mask(it,s,cmd);
        if(ret<0)return ret;
 
+       __comedi_errno = ENOTSUPPORTED;
+
        if(cmd->start_src&TRIG_NOW){
                cmd->start_src=TRIG_NOW;
                cmd->start_arg=0;
@@ -44,25 +72,34 @@ int comedi_get_cmd_generic_timed(comedi_t *it,unsigned int s,comedi_cmd *cmd)
                cmd->start_src=TRIG_FOLLOW;
                cmd->start_arg=0;
        }else{
-               /* hmmm... don't know what to do */
+               DEBUG(3,"can't find good start_src\n");
                return -1;
        }
 
+       /* Potential bug: there is a possibility that the source mask may
+        * have * TRIG_TIMER set for both convert_src and scan_begin_src,
+        * but they may not be supported together. */
        if(cmd->convert_src&TRIG_TIMER){
                if(cmd->scan_begin_src&TRIG_FOLLOW){
                        cmd->convert_src = TRIG_TIMER;
+                       cmd->convert_arg = ns;
                        cmd->scan_begin_src = TRIG_FOLLOW;
+                       cmd->scan_begin_arg = 0;
                }else{
                        cmd->convert_src = TRIG_TIMER;
+                       cmd->convert_arg = ns;
                        cmd->scan_begin_src = TRIG_TIMER;
+                       cmd->scan_begin_arg = ns;
                }
        }else if(cmd->convert_src & TRIG_NOW &&
                cmd->scan_begin_src & TRIG_TIMER)
        {
                cmd->convert_src = TRIG_NOW;
+               cmd->convert_arg = 0;
                cmd->scan_begin_src = TRIG_TIMER;
+               cmd->scan_begin_arg = ns;
        }else{
-               //printf("can't do timed?!?\n");
+               DEBUG(3,"comedi_get_cmd_generic_timed: can't do timed?\n");
                return -1;
        }
 
@@ -76,20 +113,51 @@ int comedi_get_cmd_generic_timed(comedi_t *it,unsigned int s,comedi_cmd *cmd)
                cmd->stop_src=TRIG_NONE;
                cmd->stop_arg=0;
        }else{
-               printf("can't find a good stop_src\n");
+               DEBUG(3,"comedi_get_cmd_generic_timed: can't find a good stop_src\n");
                return -1;
        }
 
        cmd->chanlist_len = 1;
 
        ret=comedi_command_test(it,cmd);
+       DEBUG(3,"comedi_get_cmd_generic_timed: test 1 returned %d\n",ret);
        if(ret==3){
                /* good */
                ret=comedi_command_test(it,cmd);
+               DEBUG(3,"comedi_get_cmd_generic_timed: test 2 returned %d\n",ret);
        }
        if(ret==4 || ret==0){
+               __comedi_errno = 0;
                return 0;
        }
        return -1;
 }
 
+int comedi_get_cmd_generic_timed(comedi_t *it,unsigned int subd,comedi_cmd *cmd,
+       unsigned int ns)
+{
+       subdevice *s;
+       int ret;
+
+       if(!valid_subd(it,subd))return -1;
+
+       s=it->subdevices+subd;
+
+       if(s->cmd_timed_errno){
+               errno = s->cmd_mask_errno;
+               return -1;
+       }
+
+       if(!s->cmd_timed){
+               s->cmd_timed = malloc(sizeof(comedi_cmd));
+
+               ret = __generic_timed(it,subd,s->cmd_timed,ns);
+               if(ret<0){
+                       s->cmd_mask_errno = errno;
+                       return -1;
+               }
+       }
+       *cmd=*s->cmd_timed;
+       return 0;
+}
+
index 0f9c5c4e876395cd17102acfdf70cc7e60bba2e2..2b7499b99d24e20b7915bac624ec6716128c9dcb 100644 (file)
 
 #include <libinternal.h>
 
-int __comedi_init=0;
+INTERNAL int __comedi_init=0;
 
-void initialize(void)
+INTERNAL void initialize(void)
 {
        char *s;
        
        __comedi_init=1;
 
        if( (s=getenv("COMEDILIB_LOGLEVEL")) ){
-               __comedi_loglevel=strtol(s,NULL,10);
-               fprintf(stderr,"setting loglevel to %d\n",__comedi_loglevel);
+               __comedi_loglevel=strtol(s,NULL,0);
+               DEBUG(3,"setting loglevel to %d\n",__comedi_loglevel);
        }
 }
   
@@ -111,6 +111,8 @@ int comedi_close(comedi_t *it)
                }else{
                        free(s->rangeinfo);
                }
+               if(s->cmd_mask)free(s->cmd_mask);
+               if(s->cmd_timed)free(s->cmd_timed);
        }
        if(it->subdevices){
                free(it->subdevices);
@@ -151,6 +153,11 @@ int comedi_command(comedi_t *it,comedi_cmd *t)
        int ret;
        ret = ioctl(it->fd,COMEDI_CMD,t);
        __comedi_errno = errno;
+       switch(__comedi_errno){
+       case EIO:
+               __comedi_errno = ECMDNOTSUPP;
+               break;
+       }
        return ret;
 }
 
@@ -159,6 +166,11 @@ int comedi_command_test(comedi_t *it,comedi_cmd *t)
        int ret;
        ret = ioctl(it->fd,COMEDI_CMDTEST,t);
        __comedi_errno = errno;
+       switch(__comedi_errno){
+       case EIO:
+               __comedi_errno = ECMDNOTSUPP;
+               break;
+       }
        return ret;
 }
 
index af314105a6b9de27cf78ac8a6ac210d6ecb61054..04b157417d7d4a1bfb26146dbdfca306ddffe433 100644 (file)
@@ -3,21 +3,21 @@
     header file for comedi's symbolic error names
 
     COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 1997-2000 David A. Schleef <ds@stm.lbl.gov>
+    Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
 
     This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
+    it under the terms of the GNU Lesser General Public License as
+    ublished by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
 
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+    You should have received a copy of the GNU Lesser General Public
+    License along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Cambridge, MA 02111, USA.
 
 */
 
 #endif
 
 // define symbolic error names, extensions peculiar to comedi
-#define COMEDI_NOERROR         0X1000
+#define COMEDI_NOERROR         0x1000
 
 #define EUNKNOWN               (COMEDI_NOERROR + 1)            // unknown error
-#define EBAD_CT                (COMEDI_NOERROR + 2)            // bad comedi_t struct
+#define EBAD_CT                        (COMEDI_NOERROR + 2)            // bad comedi_t struct
 #define EINVAL_SUBD            (COMEDI_NOERROR + 3)            // invalid subdevice
 #define EINVAL_CHAN            (COMEDI_NOERROR + 4)            // invalid channel
 #define EBUF_OVR               (COMEDI_NOERROR + 5)            // buffer overflow
 #define EBUF_UNDR              (COMEDI_NOERROR + 6)            // buffer underflow
+#define ECMDNOTSUPP            (COMEDI_NOERROR + 7)            // command not supported
+#define ENOTSUPPORTED          (COMEDI_NOERROR + 8)            // not supported
 
 #endif // _COMEDI_ERRNO_H
index f92f9a5ceb14d696d85d7558c8609c68f80c064d..3d52c336087f7c3eae92b7f6c56e04b16883cd82 100644 (file)
@@ -35,7 +35,10 @@ char *__comedilib_error_strings[]={
        "Invalid channel",
        "Buffer overflow",
        "Buffer underflow",
+       "Command not supported",
+       "Not supported",
 };
+#define n_errors (sizeof(__comedilib_error_strings)/sizeof(void *))
 
 int __comedi_loglevel=1;
 int __comedi_errno=0;
@@ -56,9 +59,7 @@ int comedi_errno(void)
 
 char *comedi_strerror(int errnum)
 {
-       if(errnum<COMEDI_NOERROR ||
-          errnum>=COMEDI_NOERROR+sizeof(__comedilib_error_strings)
-          /sizeof(__comedilib_error_strings[0]))
+       if(errnum<COMEDI_NOERROR || errnum>=COMEDI_NOERROR+n_errors)
                return strerror(errnum);
 
        return __comedilib_error_strings[errnum-COMEDI_NOERROR];
index 739045950525837b1828ea5d30c896e4237026e1..718f67ab23446c996027f4cafa258700f3c8e091 100644 (file)
 #include <fcntl.h>
 #include <stdio.h>
 
+#include <comedi_errno.h>
+
+
+/* This indicates a symbol that should not be exported as part of
+ * the library.  But I don't know how to make it useful yet. */
+#define INTERNAL
+
 
 #define debug_ptr(a)    if(!(a))fprintf(stderr," ** NULL pointer: " __FILE__ ", line %d\n",__LINE__);
 #define debug_int(a)    if((a)<0)fprintf(stderr," ** error: " __FILE__ ", line %d\n",__LINE__);
 
-#define COMEDILIB_MAGIC 0xc001dafe
+#define DEBUG(level,format,args...) do{if(__comedi_loglevel>=(level))fprintf(stderr,__FUNCTION__ ": " format, ## args);}while(0)
 
+#define COMEDILIB_MAGIC 0xc001dafe
 
 extern int __comedi_init;
 extern int __comedi_loglevel;
@@ -92,6 +100,11 @@ struct subdevice_struct{
 
        unsigned int has_cmd;
        unsigned int has_insn_bits;
+
+       int cmd_mask_errno;
+       comedi_cmd *cmd_mask;
+       int cmd_timed_errno;
+       comedi_cmd *cmd_timed;
 };