1 /* ==================================================================== */
2 /* Implement Vd80 sampler library */
3 /* Julian Lewis Wed 15th April 2009 */
4 /* ==================================================================== */
6 /* ==================================================================== */
7 /* ==================================================================== */
8 /* I very strongly recomend that this library is used in its ".so" form */
9 /* where it is loaded from the STUB library. The stub library has many */
10 /* extra routines and generic features, and calls any version of this */
11 /* library. If you insist on a static link with this library, at least */
12 /* take a look at the stub library for examples on how to use this one. */
13 /* The test program calls this library via a dynamic link and can call */
14 /* any of these functions. */
15 /* ==================================================================== */
16 /* ==================================================================== */
20 #include <sys/types.h>
24 #include <sys/ioctl.h>
35 #include <skeluser_ioctl.h>
41 /* ==================================================================== */
42 /* ==================================================================== */
43 /* Static private non exported routines for local use only. */
44 /* ==================================================================== */
45 /* ==================================================================== */
47 /* ==================================================================== */
48 /* Internal routine to select module */
50 static int SetModule(int fd
, int mod
) {
54 if (ioctl(fd
, SkelDrvrIoctlGET_MODULE_COUNT
,&cnt
) < 0) return Vd80ErrIO
;
55 if ((mod
< 1) || (mod
> cnt
)) return Vd80ErrMODULE
;
56 if (ioctl(fd
,SkelDrvrIoctlSET_MODULE
,&mod
) < 0) return Vd80ErrIO
;
57 return Vd80ErrSUCCESS
;
60 /* ==================================================================== */
62 static int DoCommand(int fd
, int mod
, int chn
, int cmd
) {
67 err
= SetModule(fd
,mod
);
68 if (err
!= Vd80ErrSUCCESS
) return err
;
71 if (cmd
== VD80_COMMAND_READ
) {
72 val
|= (VD80_OPERANT_MASK
& ((chn
-1) << VD80_OPERANT_SHIFT
));
75 if (ioctl(fd
,Vd80IoctlSET_COMMAND
,&val
) < 0) return Vd80ErrIO
;
77 return Vd80ErrSUCCESS
;
80 /* ==================================================================== */
81 /* ==================================================================== */
82 /* Exported routines */
83 /* ==================================================================== */
84 /* ==================================================================== */
86 /* ==================================================================== */
87 /* Open driver handle */
89 int vd80OpenHandle() {
94 for (i
= 1; i
<=SkelDrvrCLIENT_CONTEXTS
; i
++) {
95 sprintf(fnm
,"/dev/vd80.%1d",i
);
96 if ((fd
= open(fnm
,O_RDWR
,0)) > 0) return fd
;
101 /* ==================================================================== */
102 /* Close driver handle */
104 void vd80CloseHandle(int fd
) {
109 /* ==================================================================== */
112 Vd80Err
vd80ResetMod(int fd
, int mod
) {
116 err
= SetModule(fd
,mod
);
117 if (err
!= Vd80ErrSUCCESS
) return err
;
118 if (ioctl(fd
,SkelDrvrIoctlRESET
,NULL
) < 0) return Vd80ErrIO
;
119 return Vd80ErrSUCCESS
;
122 /* ==================================================================== */
123 /* Set debug mask options */
125 Vd80Err
vd80SetDebug(int fd
, Vd80Debug
*deb
) {
127 if (ioctl(fd
,SkelDrvrIoctlSET_DEBUG
,deb
) < 0) return Vd80ErrIO
;
128 return Vd80ErrSUCCESS
;
131 /* ==================================================================== */
132 /* Get debug mask options */
134 Vd80Err
vd80GetDebug(int fd
, Vd80Debug
*deb
) {
136 if (ioctl(fd
,SkelDrvrIoctlGET_DEBUG
,deb
) < 0) return Vd80ErrIO
;
137 return Vd80ErrSUCCESS
;
140 /* ==================================================================== */
141 /* Get instantaneous ADC value for a given channel and module */
143 Vd80Err
vd80GetAdcValue(int fd
, int mod
, int chn
, int *adc
) {
149 err
= SetModule(fd
,mod
);
150 if (err
!= Vd80ErrSUCCESS
) return err
;
153 if (ioctl(fd
,Vd80IoctlREAD_ADC
,&val
) < 0) return Vd80ErrIO
;
156 return Vd80ErrSUCCESS
;
159 /* ==================================================================== */
160 /* Get State, the chn parameter is ignored, the state is for the module */
162 Vd80Err
vd80GetState(int fd
, int mod
, int chn
, Vd80State
*ste
) {
167 err
= SetModule(fd
,mod
);
168 if (err
!= Vd80ErrSUCCESS
) return err
;
170 if (ioctl(fd
,Vd80IoctlGET_STATE
,&val
) < 0) return Vd80ErrIO
;
171 *ste
= (Vd80State
) val
;
172 return Vd80ErrSUCCESS
;
175 /* ==================================================================== */
178 Vd80Err
vd80GetStatus(int fd
, int mod
, Vd80Status
*sts
) {
183 err
= SetModule(fd
,mod
);
184 if (err
!= Vd80ErrSUCCESS
) return err
;
186 if (ioctl(fd
, SkelDrvrIoctlGET_STATUS
, &val
) < 0) return Vd80ErrIO
;
187 *sts
= (Vd80Status
) val
;
188 return Vd80ErrSUCCESS
;
191 /* ==================================================================== */
194 Vd80Err
vd80GetDatumSize(int fd
, Vd80DatumSize
*dsz
) {
196 *dsz
= Vd80DatumSize16
;
197 return Vd80ErrSUCCESS
;
200 /* ==================================================================== */
201 /* Get installed module count */
203 Vd80Err
vd80GetModuleCount(int fd
, int *cnt
) {
205 if (ioctl(fd
, SkelDrvrIoctlGET_MODULE_COUNT
,cnt
) < 0) return Vd80ErrIO
;
206 return Vd80ErrSUCCESS
;
209 /* ==================================================================== */
210 /* Get number of channels */
212 Vd80Err
vd80GetChannelCount(int fd
, int *cnt
) {
214 *cnt
= VD80_CHANNELS
;
215 return Vd80ErrSUCCESS
;
218 /* ==================================================================== */
219 /* Get driver and hardware version */
222 #define COMPILE_TIME 0
225 Vd80Err
vd80GetVersion(int fd
, int mod
, Vd80Version
*ver
) {
228 SkelDrvrVersion skver
;
230 err
= SetModule(fd
,mod
);
231 if (err
!= Vd80ErrSUCCESS
) return err
;
233 if (ioctl(fd
,SkelDrvrIoctlGET_VERSION
,&skver
) < 0) return Vd80ErrIO
;
235 ver
->LibraryVersion
= COMPILE_TIME
;
236 ver
->DriverVersion
= skver
.DriverVersion
;
237 strncpy(ver
->ModVersion
,skver
.ModuleVersion
,Vd80VERSION_SIZE
);
238 return Vd80ErrSUCCESS
;
241 /* ==================================================================== */
242 /* Actually there is one trigger setting per module only, not for each */
243 /* channel !!! chns is ignored. */
245 Vd80Err
vd80SetTrigger(int fd
, unsigned int mods
, unsigned int chns
, Vd80Input
*inp
) {
252 for (i
=0; i
<Vd80MODULES
; i
++) {
257 err
= SetModule(fd
,mod
);
258 if (err
!= Vd80ErrSUCCESS
) return err
;
261 if (ioctl(fd
,Vd80IoctlSET_TRIGGER_EDGE
,&val
) < 0) return Vd80ErrIO
;
262 val
= inp
->Termination
;
263 if (ioctl(fd
,Vd80IoctlSET_TRIGGER_TERMINATION
,&val
) < 0) return Vd80ErrIO
;
265 if (ioctl(fd
,Vd80IoctlSET_TRIGGER
,&val
) < 0) return Vd80ErrIO
;
268 return Vd80ErrSUCCESS
;
271 /* ==================================================================== */
272 /* Get trigger input options. chn is ignored */
274 Vd80Err
vd80GetTrigger(int fd
, int mod
, int chn
, Vd80Input
*inp
) {
279 err
= SetModule(fd
,mod
);
280 if (err
!= Vd80ErrSUCCESS
) return err
;
282 if (ioctl(fd
,Vd80IoctlGET_TRIGGER_EDGE
,&val
) < 0) return Vd80ErrIO
;
284 if (ioctl(fd
,Vd80IoctlGET_TRIGGER_TERMINATION
,&val
) < 0) return Vd80ErrIO
;
285 inp
->Termination
= val
;
286 if (ioctl(fd
,Vd80IoctlGET_TRIGGER
,&val
) < 0) return Vd80ErrIO
;
289 return Vd80ErrSUCCESS
;
292 /* ==================================================================== */
293 /* Set clock input settings. chns are ignored */
295 Vd80Err
vd80SetClock(int fd
, unsigned int mods
, unsigned int chns
, Vd80Input
*inp
) {
302 for (i
=0; i
<Vd80MODULES
; i
++) {
307 err
= SetModule(fd
,mod
);
308 if (err
!= Vd80ErrSUCCESS
) return err
;
311 if (ioctl(fd
,Vd80IoctlSET_CLOCK_EDGE
,&val
) < 0) return Vd80ErrIO
;
312 val
= inp
->Termination
;
313 if (ioctl(fd
,Vd80IoctlSET_CLOCK_TERMINATION
,&val
) < 0) return Vd80ErrIO
;
315 if (ioctl(fd
,Vd80IoctlSET_CLOCK
,&val
) < 0) return Vd80ErrIO
;
318 return Vd80ErrSUCCESS
;
321 /* ==================================================================== */
322 /* Get clock input settings */
324 Vd80Err
vd80GetClock(int fd
, int mod
, int chn
, Vd80Input
*inp
) {
329 err
= SetModule(fd
,mod
);
330 if (err
!= Vd80ErrSUCCESS
) return err
;
332 if (ioctl(fd
,Vd80IoctlGET_CLOCK_EDGE
,&val
) < 0) return Vd80ErrIO
;
334 if (ioctl(fd
,Vd80IoctlGET_CLOCK_TERMINATION
,&val
) < 0) return Vd80ErrIO
;
335 inp
->Termination
= val
;
336 if (ioctl(fd
,Vd80IoctlGET_CLOCK
,&val
) < 0) return Vd80ErrIO
;
339 return Vd80ErrSUCCESS
;
342 /* ==================================================================== */
343 /* Set clock sample rate */
345 Vd80Err
vd80SetClockDivide(int fd
, unsigned int mods
, unsigned int chns
, unsigned int dvd
) {
352 for (i
=0; i
<Vd80MODULES
; i
++) {
357 err
= SetModule(fd
,mod
);
358 if (err
!= Vd80ErrSUCCESS
) return err
;
360 val
= VD80_CLKDIVMODE_DIVIDE
;
361 if (ioctl(fd
,Vd80IoctlSET_CLOCK_DIVIDE_MODE
,&val
) < 0) return Vd80ErrIO
;
364 if (ioctl(fd
,Vd80IoctlSET_CLOCK_DIVISOR
,&val
) < 0) return Vd80ErrIO
;
367 return Vd80ErrSUCCESS
;
370 /* ==================================================================== */
371 /* Get clock sample rate */
373 Vd80Err
vd80GetClockDivide(int fd
, int mod
, int chn
, unsigned int *dvd
) {
378 err
= SetModule(fd
,mod
);
379 if (err
!= Vd80ErrSUCCESS
) return err
;
381 if (ioctl(fd
,Vd80IoctlGET_CLOCK_DIVISOR
,&val
) < 0) return Vd80ErrIO
;
383 return Vd80ErrSUCCESS
;
386 /* ==================================================================== */
387 /* Start acquisition, state will be pretrigger */
389 Vd80Err
vd80StrtAcquisition(int fd
, unsigned int mods
, unsigned int chns
) {
395 for (i
=0; i
<Vd80MODULES
; i
++) {
400 err
= DoCommand(fd
,mod
,0,Vd80DrvrCommandSTART
);
401 if (err
!= Vd80ErrSUCCESS
) return err
;
404 return Vd80ErrSUCCESS
;
407 /* ==================================================================== */
408 /* Trigger acquisition, state will be posttrigger */
410 Vd80Err
vd80TrigAcquisition(int fd
, unsigned int mods
, unsigned int chns
) {
416 for (i
=0; i
<Vd80MODULES
; i
++) {
421 err
= DoCommand(fd
,mod
,0,Vd80DrvrCommandTRIGGER
);
422 if (err
!= Vd80ErrSUCCESS
) return err
;
425 return Vd80ErrSUCCESS
;
428 /* ==================================================================== */
429 /* Stop acquisition, state will be idle */
431 Vd80Err
vd80StopAcquisition(int fd
, unsigned int mods
, unsigned int chns
) {
437 for (i
=0; i
<Vd80MODULES
; i
++) {
442 err
= DoCommand(fd
,mod
,0,Vd80DrvrCommandSTOP
);
443 if (err
!= Vd80ErrSUCCESS
) return err
;
446 return Vd80ErrSUCCESS
;
449 /* ==================================================================== */
450 /* Connect to module interrupt */
452 Vd80Err
vd80Connect(int fd
, unsigned int mods
, unsigned int chns
, unsigned int imsk
) {
454 SkelDrvrConnection conn
;
460 for (i
=0; i
<Vd80MODULES
; i
++) {
465 err
= SetModule(fd
,mod
);
466 if (err
!= Vd80ErrSUCCESS
) return err
;
470 if (ioctl(fd
,SkelDrvrIoctlCONNECT
, &conn
) < 0) return Vd80ErrIO
;
474 return Vd80ErrSUCCESS
;
477 /* ==================================================================== */
478 /* Set wait timeout, 0 means wait for ever */
480 Vd80Err
vd80SetTimeout(int fd
, int tmo
) {
482 if (ioctl(fd
,SkelDrvrIoctlSET_TIMEOUT
,&tmo
) < 0) return Vd80ErrIO
;
483 return Vd80ErrSUCCESS
;
486 /* ==================================================================== */
487 /* Get wait timeout, 0 means wait for ever */
489 Vd80Err
vd80GetTimeout(int fd
, int *tmo
) {
491 if (ioctl(fd
,SkelDrvrIoctlGET_TIMEOUT
,tmo
) < 0) return Vd80ErrIO
;
492 return Vd80ErrSUCCESS
;
495 /* ==================================================================== */
496 /* Set interrupt queueing on or off */
498 Vd80Err
vd80SetQueueFlag(int fd
, Vd80QueueFlag qfl
) {
500 if (ioctl(fd
,SkelDrvrIoctlSET_QUEUE_FLAG
,&qfl
) < 0) return Vd80ErrIO
;
501 return Vd80ErrSUCCESS
;
504 /* ==================================================================== */
505 /* Get interrupt queueing on or off */
507 Vd80Err
vd80GetQueueFlag(int fd
, Vd80QueueFlag
*qfl
) {
509 if (ioctl(fd
,SkelDrvrIoctlGET_QUEUE_FLAG
,qfl
) < 0) return Vd80ErrIO
;
510 return Vd80ErrSUCCESS
;
513 /* ==================================================================== */
514 /* Wait for an interrupt */
516 Vd80Err
vd80Wait(int fd
, Vd80Intr
*intr
) {
518 SkelDrvrReadBuf rbuf
;
521 bzero((void *) intr
, sizeof(Vd80Intr
));
523 ret
= read(fd
,&rbuf
,sizeof(SkelDrvrReadBuf
));
524 if (ret
== 0) return Vd80ErrTIMEOUT
;
526 if (ioctl(fd
,SkelDrvrIoctlGET_QUEUE_SIZE
,&qsz
) < 0) return Vd80ErrIO
;
527 if (ioctl(fd
,SkelDrvrIoctlGET_QUEUE_OVERFLOW
,&qov
) < 0) return Vd80ErrIO
;
529 intr
->Mask
= rbuf
.Connection
.ConMask
;
530 intr
->Time
.tv_sec
= rbuf
.Time
.Second
;
531 intr
->Time
.tv_nsec
= rbuf
.Time
.NanoSecond
;
532 intr
->Module
= rbuf
.Connection
.Module
;
534 intr
->QueueSize
= qsz
;
537 return Vd80ErrSUCCESS
;
540 /* ==================================================================== */
541 /* Simulate an interrupt */
543 Vd80Err
vd80SimulateInterrupt(int fd
, Vd80Intr
*intr
) {
545 SkelDrvrReadBuf rbuf
;
548 rbuf
.Connection
.ConMask
= intr
->Mask
;
549 rbuf
.Connection
.Module
= intr
->Module
;
551 ret
= write(fd
,&rbuf
,sizeof(SkelDrvrReadBuf
));
552 if (ret
== 0) return Vd80ErrTIMEOUT
;
554 return Vd80ErrSUCCESS
;
557 /* ==================================================================== */
558 /* Set module buffer size and post sample count */
560 Vd80Err
vd80SetBufferSize(int fd
, unsigned int mods
, unsigned int chns
, int bsze
, int post
) {
566 for (i
=0; i
<Vd80MODULES
; i
++) {
571 err
= SetModule(fd
,mod
);
572 if (err
!= Vd80ErrSUCCESS
) return err
;
574 if (ioctl(fd
,Vd80IoctlSET_POSTSAMPLES
,&post
) < 0) return Vd80ErrIO
;
577 return Vd80ErrSUCCESS
;
580 /* ==================================================================== */
581 /* Get requested number of post samples */
583 Vd80Err
vd80GetBufferSize(int fd
, unsigned int mod
, int *post
) {
587 err
= SetModule(fd
,mod
);
588 if (err
!= Vd80ErrSUCCESS
) return err
;
589 if (ioctl(fd
,Vd80IoctlGET_POSTSAMPLES
,&post
) < 0) return Vd80ErrIO
;
590 return Vd80ErrSUCCESS
;
593 /* ==================================================================== */
594 /* Need to know if bytes must be swapped */
597 static int little_endian() {
599 char *p
= (char *) &i
;
605 /* ==================================================================== */
606 /* Transfer module data by DMA to users buffer */
608 Vd80Err
vd80GetBuffer(int fd
, int mod
, int chn
, Vd80Buffer
*buf
) {
614 err
= DoCommand(fd
,mod
,chn
,Vd80DrvrCommandREAD
);
615 if (err
!= Vd80ErrSUCCESS
) return err
;
617 tps
= buf
->BSze
- buf
->Post
-1;
618 if (tps
< 0) tps
= 0;
620 sbuf
.SampleBuf
= buf
->Addr
;
621 sbuf
.BufSizeSamples
= buf
->BSze
;
623 sbuf
.TrigPosition
= tps
;
626 if (ioctl(fd
,Vd80IoctlREAD_SAMPLE
,&sbuf
) < 0) return Vd80ErrIO
;
628 buf
->Tpos
= sbuf
.TrigPosition
;
629 buf
->ASze
= sbuf
.Samples
;
630 buf
->Ptsr
= sbuf
.PreTrigStat
;
632 return Vd80ErrSUCCESS
;
635 /* ==================================================================== */
636 /* Set the trigger analogue levels */
638 Vd80Err
vd80SetTriggerLevels(int fd
, unsigned int mods
, unsigned int chns
, Vd80AnalogTrig
*atrg
) {
641 unsigned int mski
, mskj
;
643 Vd80DrvrAnalogTrig adtrg
;
645 if (mods
== Vd80ModNONE
) mods
= Vd80Mod01
;
646 if (chns
== Vd80ChnNONE
) chns
= Vd80Chn01
;
648 for (i
=0; i
<Vd80MODULES
; i
++) {
653 err
= SetModule(fd
,mod
);
654 if (err
!= Vd80ErrSUCCESS
) return err
;
656 for (j
=0; j
<Vd80CHANNELS
; j
++) {
663 adtrg
.Control
= atrg
->AboveBelow
;
664 adtrg
.Level
= atrg
->TrigLevel
;
666 if (ioctl(fd
,Vd80IoctlSET_ANALOGUE_TRIGGER
,&adtrg
) < 0) return Vd80ErrIO
;
671 return Vd80ErrSUCCESS
;
674 /* ==================================================================== */
675 /* Get the trigger analogue level */
677 Vd80Err
vd80GetTriggerLevels(int fd
, int mod
, int chn
, Vd80AnalogTrig
*atrg
) {
680 Vd80DrvrAnalogTrig adtrg
;
682 if (mod
== Vd80ModNONE
) mod
= Vd80Mod01
;
683 if (chn
== Vd80ChnNONE
) chn
= Vd80Chn01
;
685 err
= SetModule(fd
,mod
);
686 if (err
!= Vd80ErrSUCCESS
) return err
;
690 if (ioctl(fd
,Vd80IoctlGET_ANALOGUE_TRIGGER
,&adtrg
) < 0) return Vd80ErrIO
;
692 atrg
->AboveBelow
= adtrg
.Control
;
693 atrg
->TrigLevel
= adtrg
.Level
;
695 return Vd80ErrSUCCESS
;
698 /* ==================================================================== */
699 /* Set trigger configuration params, delay and min pretrig samples */
701 Vd80Err
vd80SetTriggerConfig(int fd
, unsigned int mods
, unsigned int chns
, Vd80TrigConfig
*ctrg
) {
704 unsigned int mski
, mskj
;
706 Vd80DrvrTrigConfig cdtrg
;
708 if (mods
== Vd80ModNONE
) mods
= Vd80Mod01
;
709 if (chns
== Vd80ChnNONE
) chns
= Vd80Chn01
;
711 for (i
=0; i
<Vd80MODULES
; i
++) {
716 err
= SetModule(fd
,mod
);
717 if (err
!= Vd80ErrSUCCESS
) return err
;
719 for (j
=0; j
<Vd80CHANNELS
; j
++) {
725 cdtrg
.TrigDelay
= ctrg
->TrigDelay
;
726 cdtrg
.MinPreTrig
= ctrg
->MinPreTrig
;
728 if (ioctl(fd
,Vd80IoctlSET_TRIGGER_CONFIG
,&cdtrg
) < 0)
735 return Vd80ErrSUCCESS
;
738 /* ==================================================================== */
739 /* Get trigger configuration params, delay and min pretrig samples */
741 Vd80Err
vd80GetTriggerConfig(int fd
, int mod
, int chn
, Vd80TrigConfig
*ctrg
) {
744 Vd80DrvrTrigConfig cdtrg
;
746 if (mod
== Vd80ModNONE
) mod
= Vd80Mod01
;
747 if (chn
== Vd80ChnNONE
) chn
= Vd80Chn01
;
749 err
= SetModule(fd
,mod
);
750 if (err
!= Vd80ErrSUCCESS
) return err
;
752 if (ioctl(fd
,Vd80IoctlGET_TRIGGER_CONFIG
,&cdtrg
) < 0) return Vd80ErrIO
;
754 ctrg
->TrigDelay
= cdtrg
.TrigDelay
;
755 ctrg
->MinPreTrig
= cdtrg
.MinPreTrig
;
757 return Vd80ErrSUCCESS
;
760 /* ==================================================================== */
761 /* Convert an error to a string */
763 static char *ErrTexts
[Vd80ERRORS
] = {
764 "All went OK, No error ", // Vd80ErrSUCCESS,
765 "Function is not implemented on this device ", // Vd80ErrNOT_IMP,
766 "Invalid Start value for this device ", // Vd80ErrSTART,
767 "Invalid Mode value for this device ", // Vd80ErrMODE,
768 "Invalid Clock value for this device ", // Vd80ErrCLOCK,
769 "Can't open a driver file handle, fatal ", // Vd80ErrOPEN,
770 "Can't connect to that interrupt ", // Vd80ErrCONNECT,
771 "No connections to wait for ", // Vd80ErrWAIT,
772 "Timeout in wait ", // Vd80ErrTIMEOUT,
773 "Queue flag must be set 0 queueing is needed", // Vd80ErrQFLAG,
774 "IO or BUS error ", // Vd80ErrIO,
775 "Module is not enabled ", // Vd80ErrNOT_ENAB
776 "Not available for INTERNAL sources ", // Vd80ErrSOURCE,
777 "Value out of range ", // Vd80ErrVOR,
778 "Bad device type ", // Vd80ErrDEVICE,
779 "Bad address ", // Vd80ErrADDRESS,
780 "Can not allocate memory ", // Vd80ErrMEMORY,
781 "Shared library error, can't open object ", // Vd80ErrDLOPEN,
782 "Shared library error, can't find symbol ", // Vd80ErrDLSYM,
783 "Can't open sampler device driver ", // Vd80ErrDROPEN,
784 "Invalid handle ", // Vd80ErrHANDLE,
785 "Invalid module number, not installed ", // Vd80ErrMODULE,
786 "Invalid channel number for this module " // Vd80ErrCHANNEL,
789 char *vd80ErrToStr(int fd
, Vd80Err error
) {
791 char *cp
; /* Char pointer */
793 static char err
[Vd80ErrSTRING_SIZE
]; /* Static text area when null handle */
795 bzero((void *) err
, Vd80ErrSTRING_SIZE
);
797 i
= (unsigned int) error
;
798 if (i
>= Vd80ERRORS
) {
799 sprintf(err
,"Vd80Lib:Invalid error code:%d Not in[0..%d]\n",i
,Vd80ERRORS
);
803 sprintf(err
,"Vd80Lib:%s",ErrTexts
[i
]);
805 /* Extra info available from errno */
807 if ((error
== Vd80ErrIO
)
808 || (error
== Vd80ErrDROPEN
)
809 || (error
== Vd80ErrMEMORY
)) {
810 cp
= strerror(errno
);
813 i
= Vd80ErrSTRING_SIZE
- strlen(err
) -1; /* -1 is 0 terminator byte */