1 #ifndef LINT
2 static char *rcsid="$Id: eph_cmd.c,v 1.20 2001/08/28 06:28:01 crosser Exp $";
3 #endif
4
5 /*
6 Copyright (c) 1997-2000 Eugene G. Crosser
7 Copyright (c) 1998 Bruce D. Lightner (DOS/Windows support)
8
9 You may distribute and/or use for any purpose modified or unmodified
10 copies of this software if you preserve the copyright notice above.
11
12 THIS SOFTWARE IS PROVIDED AS IS AND COME WITH NO WARRANTY OF ANY
13 KIND, EITHER EXPRESSED OR IMPLIED. IN NO EVENT WILL THE
14 COPYRIGHT HOLDER BE LIABLE FOR ANY DAMAGES RESULTING FROM THE
15 USE OF THIS SOFTWARE.
16 */
17
18 /*
19 $Log: eph_cmd.c,v $
20 Revision 1.20 2001/08/28 06:28:01 crosser
21 try make zoom working on newer Oly
22
23 Revision 1.19 2000/05/09 13:20:54 crosser
24 configure read() with alarm() better.
25 Address signed vs. unsigned arguments
26 other cleanups to make most notorious compilers happy
27
28 Revision 1.18 2000/05/02 22:26:35 crosser
29 A few things incorporated from John Bowman's Nikon specific diffs
30
31 Revision 1.17 2000/05/02 12:13:32 crosser
32 some better debugging output
33 alarm() based timeouted read (build with "--without-select")
34
35 Revision 1.16 2000/02/13 11:15:01 crosser
36 Kludge null setint for Nikon
37
38 Revision 1.15 1999/08/01 21:36:54 crosser
39 Modify source to suit ansi2knr
40 (I hate the style that ansi2knr requires but you don't expect me
41 to write another smarter ansi2knr implementation, right?)
42
43 Revision 1.14 1999/07/28 19:56:31 crosser
44 reorder includes
45
46 Revision 1.13 1999/03/21 20:22:09 crosser
47 change retry logic for first block (for Agfa 307)
48
49 Revision 1.12 1999/03/06 13:37:08 crosser
50 Convert to autoconf-style
51
52 Revision 1.11 1999/01/21 09:12:56 crosser
53 fix of retry logic from Richard Sharman
54
55 Revision 1.10 1998/10/18 13:18:27 crosser
56 Put RCS logs and I.D. into the source
57
58 Revision 1.9 1998/08/09 13:24:59 crosser
59 cleanup for DOS
60
61 Revision 1.8 1998/08/09 12:57:56 crosser
62 make right running report on 16bit architecture
63
64 Revision 1.7 1998/02/26 00:50:39 crosser
65 extra error message
66
67 Revision 1.6 1998/02/16 06:15:44 lightner
68 Parameterize tmpbuf size; fix tmpbuf memory leak
69
70 Revision 1.5 1998/02/08 19:58:38 crosser
71 Support low memory: chunked saving etc.
72
73 Revision 1.4 1998/02/05 23:29:17 lightner
74 Force 32-bit math in eph_getint()
75 Only realloc() an extra 2048 bytes when buffer too small (DOS only)
76
77 Revision 1.3 1998/01/27 21:52:23 crosser
78 add NANOSLEEP
79
80 Revision 1.2 1998/01/18 02:16:45 crosser
81 DOS support
82
83 Revision 1.1 1997/08/17 08:59:54 crosser
84 Initial revision
85
86 */
87
88 #ifdef HAVE_CONFIG_H
89 #include "config.h"
90 #endif
91 #include <stdio.h>
92 #include "eph_io.h"
93 #include "eph_priv.h"
94
95 #define TMPBUF_SIZE (2048)
96
97 #define MAYRETRY(rc) ((rc == -2) || (rc == NAK))
98
99 int
eph_writecmd(eph_iob * iob,char * data,size_t length)100 eph_writecmd(eph_iob *iob,char *data,size_t length)
101 {
102 return eph_writepkt(iob,PKT_CMD,SEQ_CMD,data,length);
103 }
104
105 int
eph_writeicmd(eph_iob * iob,char * data,size_t length)106 eph_writeicmd(eph_iob *iob,char *data,size_t length)
107 {
108 return eph_writepkt(iob,PKT_CMD,SEQ_INITCMD,data,length);
109 }
110
111 int
eph_setispeed(eph_iob * iob,long val)112 eph_setispeed(eph_iob *iob,long val)
113 {
114 unsigned char buf[6];
115 int rc;
116 int count=0;
117
118 buf[0]=CMD_SETINT;
119 buf[1]=REG_SPEED;
120 buf[2]=(val)&0xff;
121 buf[3]=(val>>8)&0xff;
122 buf[4]=(val>>16)&0xff;
123 buf[5]=(val>>24)&0xff;
124 do {
125 if ((rc=eph_writeicmd(iob,buf,6))) return rc;
126 rc=eph_waitack(iob,ACKTIMEOUT);
127 } while (rc && (count++ < RETRIES));
128 if (count >= RETRIES)
129 eph_error(iob,ERR_EXCESSIVE_RETRY,
130 "excessive retries on setispeed");
131 if (iob->debug) printf("setispeed(%ld) rc=%d\n",val,rc);
132 return rc;
133 }
134
135 int
eph_setint(eph_iob * iob,int reg,long val)136 eph_setint(eph_iob *iob,int reg,long val)
137 {
138 unsigned char buf[6];
139 int rc;
140 int count=0;
141
142 buf[0]=CMD_SETINT;
143 buf[1]=reg;
144 buf[2]=(val)&0xff;
145 buf[3]=(val>>8)&0xff;
146 buf[4]=(val>>16)&0xff;
147 buf[5]=(val>>24)&0xff;
148
149 writeagain:
150 if ((rc=eph_writecmd(iob,buf,6))) return rc;
151 rc=eph_waitack(iob,(reg == REG_FRAME)?BIGACKTIMEOUT:ACKTIMEOUT);
152 if (MAYRETRY(rc) && (count++ < RETRIES)) goto writeagain;
153 if (count >= RETRIES)
154 eph_error(iob,ERR_EXCESSIVE_RETRY,
155 "excessive retries on setint");
156 if (iob->debug) printf("setint(%d,%ld) rc=%d\n",reg,val,rc);
157 return rc;
158 }
159
160 int
eph_setnullint(eph_iob * iob,int reg)161 eph_setnullint(eph_iob *iob,int reg)
162 {
163 unsigned char buf[2];
164 int rc;
165 int count=0;
166
167 buf[0]=CMD_SETINT;
168 buf[1]=reg;
169
170 writeagain:
171 if ((rc=eph_writecmd(iob,buf,2))) return rc;
172 rc=eph_waitack(iob,(reg == REG_FRAME)?BIGACKTIMEOUT:ACKTIMEOUT);
173 if (MAYRETRY(rc) && (count++ < RETRIES)) goto writeagain;
174 if (count >= RETRIES)
175 eph_error(iob,ERR_EXCESSIVE_RETRY,
176 "excessive retries on setnullint");
177 if (iob->debug) printf("setnullint(%d) rc=%d\n",reg,rc);
178 return rc;
179 }
180
181 int
eph_getint(eph_iob * iob,int reg,long * val)182 eph_getint(eph_iob *iob,int reg,long *val)
183 {
184 unsigned char buf[4];
185 eph_pkthdr pkt;
186 int rc;
187 size_t size=4;
188 int count=0;
189
190 (*val)=0L;
191 buf[0]=CMD_GETINT;
192 buf[1]=reg;
193
194 writeagain:
195 if ((rc=eph_writecmd(iob,buf,2))) return rc;
196 readagain:
197 rc=eph_readpkt(iob,&pkt,buf,&size,BIGDATATIMEOUT);
198 if (MAYRETRY(rc) && (count++ < RETRIES)) goto writeagain;
199 if ((rc == 0) && (pkt.typ == PKT_LAST) && (pkt.seq == 0)) {
200 (*val)=((unsigned long)buf[0]) | ((unsigned long)buf[1]<<8) |
201 ((unsigned long)buf[2]<<16) | ((unsigned long)buf[3]<<24);
202 eph_writeack(iob);
203 rc=0;
204 goto fin;
205 } else if ((rc == -1) && (count++ < RETRIES)) {
206 eph_writenak(iob);
207 goto readagain;
208 }
209 if (count >= RETRIES)
210 eph_error(iob,ERR_EXCESSIVE_RETRY,
211 "excessive retries on getint");
212 fin:
213 if (iob->debug) printf("getint(%d)=%ld, rc=%d\n",reg,*val,rc);
214 return rc;
215 }
216
217 int
eph_action(eph_iob * iob,int reg,char * val,size_t length)218 eph_action(eph_iob *iob,int reg,char *val,size_t length)
219 {
220 unsigned char buf[2050];
221 int rc;
222 int count=0;
223
224 if (length > (sizeof(buf) - 2)) {
225 eph_error(iob,ERR_DATA_TOO_LONG,"arg action length %ld",
226 (long)length);
227 return -1;
228 }
229
230 buf[0]=CMD_ACTION;
231 buf[1]=reg;
232 memcpy(buf+2,val,length);
233
234 writeagain:
235 if ((rc=eph_writecmd(iob,buf,length+2))) return rc;
236 rc=eph_waitack(iob,ACKTIMEOUT);
237
238 if (MAYRETRY(rc) && (count++ < RETRIES)) goto writeagain;
239
240 if (rc == 0) rc=eph_waitcomplete(iob);
241 if (count >= RETRIES)
242 eph_error(iob,ERR_EXCESSIVE_RETRY,
243 "excessive retries on action");
244 if (iob->debug) printf("action(%d,%p(0x%02x),%u) rc=%d\n",
245 reg,val,
246 (length==1)?(val[0]&0xff):0,
247 (unsigned int)length,rc);
248 return rc;
249 }
250
251 int
eph_setvar(eph_iob * iob,int reg,char * val,off_t olength)252 eph_setvar(eph_iob *iob,int reg,char *val,off_t olength)
253 {
254 unsigned char buf[2048];
255 int rc=0,seq=-1;
256 int count=0;
257 int pkttyp,pktseq;
258 size_t pktsize,maywrite;
259 off_t written=0;
260 off_t length=olength;
261 unsigned char *getpoint,*putpoint;
262
263 getpoint=val;
264 while (length && !rc) {
265 if (seq == -1) {
266 pkttyp=PKT_CMD;
267 pktseq=SEQ_CMD;
268 buf[0]=CMD_SETVAR;
269 buf[1]=reg;
270 putpoint=buf+2;
271 maywrite=sizeof(buf)-2;
272 pktsize=2;
273 } else {
274 pkttyp=PKT_DATA;
275 pktseq=seq;
276 putpoint=buf;
277 maywrite=sizeof(buf);
278 pktsize=0;
279 (iob->runcb)(written);
280 }
281 if ((size_t)length <= maywrite) {
282 maywrite=length;
283 if (pkttyp == PKT_DATA) pkttyp=PKT_LAST;
284 }
285 memcpy(putpoint,getpoint,maywrite);
286 pktsize+=maywrite;
287 length-=maywrite;
288 getpoint+=maywrite;
289 written+=maywrite;
290 seq++;
291 writeagain:
292 if ((rc=eph_writepkt(iob,pkttyp,pktseq,buf,pktsize)))
293 goto fin;
294 rc=eph_waitack(iob,(reg==REG_ZOOM)?BIGACKTIMEOUT:ACKTIMEOUT);
295 if (MAYRETRY(rc) && (count++ < RETRIES)) goto writeagain;
296 }
297 if (count >= RETRIES)
298 eph_error(iob,ERR_EXCESSIVE_RETRY,
299 "excessive retries on setvar");
300 fin:
301 if (iob->debug) printf("setvar(%d,\"%.60s\",%lu) rc=%d\n",
302 reg,val,(unsigned long)olength,rc);
303 return rc;
304 }
305
306 int
eph_getvar(eph_iob * iob,int reg,char ** buffer,off_t * bufsize)307 eph_getvar(eph_iob *iob,int reg,char **buffer,off_t *bufsize)
308 {
309 unsigned char buf[2];
310 eph_pkthdr pkt;
311 int rc;
312 int count=0;
313 unsigned char expect=0;
314 off_t index;
315 size_t readsize;
316 char *ptr;
317 char *tmpbuf=NULL;
318 size_t tmpbufsize=0;
319
320 if ((buffer == NULL) && (iob->storecb == NULL)) {
321 eph_error(iob,ERR_BADARGS,
322 "NULL buffer and no store callback for getvar");
323 return -1;
324 }
325
326 if (buffer == NULL) {
327 tmpbuf=(iob->realloccb)(NULL,(size_t)TMPBUF_SIZE);
328 tmpbufsize=TMPBUF_SIZE;
329 if (tmpbuf == NULL) {
330 eph_error(iob,ERR_NOMEM,
331 "could not alloc %lu for tmpbuf in getvar",
332 (long)TMPBUF_SIZE);
333 return -1;
334 }
335 }
336
337 buf[0]=CMD_GETVAR;
338 buf[1]=reg;
339
340 writeagain:
341 if ((rc=eph_writecmd(iob,buf,2))) return rc;
342 index=0;
343 readagain:
344 if (buffer) { /* read to memory reallocating it */
345 if (((*bufsize) - index) < 2048) {
346 if (iob->debug)
347 printf("reallocing %lu",(unsigned long)(*bufsize));
348 #ifdef LOWMEMORY
349 /* small memory! round up to next 2048 boundary */
350 (*bufsize)=(((index + 2048)-1)/2048L+1)*2048L;
351 #else
352 /* multiply current size by 2 and round up to 2048 boundary */
353 (*bufsize)=((((*bufsize)*2)-1)/2048+1)*2048;
354 #endif
355 if (iob->debug)
356 printf(" -> %lu\n",(unsigned long)(*bufsize));
357 (*buffer)=(iob->realloccb)(*buffer,(size_t)*bufsize);
358 if ((*buffer) == NULL) {
359 eph_error(iob,ERR_NOMEM,
360 "could not realloc %lu for getvar",
361 (long)*bufsize);
362 return -1;
363 }
364 }
365 ptr=(*buffer)+index;
366 readsize=(*bufsize)-index;
367 } else { /* pass data to store callback */
368 ptr=tmpbuf;
369 readsize=tmpbufsize;
370 }
371 rc=eph_readpkt(iob,&pkt,ptr,&readsize,
372 (expect || ((reg != REG_IMG) || (reg != REG_TMN)))?
373 DATATIMEOUT:BIGDATATIMEOUT);
374 if (MAYRETRY(rc) && (expect == 0) && (count++ < RETRIES)) {
375 eph_writenak(iob);
376 if (rc == -2) goto readagain;
377 else goto writeagain;
378 }
379 if ((rc == 0) &&
380 ((pkt.seq == expect) || (pkt.seq == (expect-1)))) {
381 count=0;
382 if (pkt.seq == expect) {
383 index+=readsize;
384 expect++;
385 (iob->runcb)(index);
386 if (buffer == NULL) {
387 if (iob->debug)
388 printf("storing %lu at %08lx\n",
389 (unsigned long)readsize,
390 (unsigned long)ptr);
391 if ((iob->storecb)(ptr,readsize))
392 return -1;
393 }
394 }
395 eph_writeack(iob);
396 if (pkt.typ == PKT_LAST) {
397 if (buffer) (*bufsize)=index;
398 if (tmpbuf) free(tmpbuf);
399 return 0;
400 }
401 else goto readagain;
402 }
403 if ((rc <= 0) && (count++ < RETRIES)) {
404 eph_writenak(iob);
405 goto readagain;
406 }
407 if (tmpbuf) free(tmpbuf);
408 if (count >= RETRIES)
409 eph_error(iob,ERR_EXCESSIVE_RETRY,
410 "excessive retries on getvar");
411 if (iob->debug) printf("getvar(%d) got %lu, rc=%d\n",
412 reg,(unsigned long)(*bufsize),rc);
413 return rc;
414 }
415