Source code upload
[framework/connectivity/libgphoto2.git] / camlibs / dimera / mesalib.c
1 /*
2 * Copyright © 2000-2001, Brian Beattie <beattie@aracnet.com>, et. al.
3 *
4 *       This software was created with the help of proprietary
5 *      information belonging to StarDot Technologies
6 *
7 * Permission to copy and use and modify this file is granted
8 * provided the above notices are retained, intact.
9 *
10 * Revision History:
11 *       See CVS log for later revisions
12 *
13 *       2001/03/10 - Port to gphoto2                                      Dan
14 *
15 *       2000/09/06 - Modified by Gregg Berg <gberg@covconn.net>           GDB
16 *               * Rewrite mesa_read_row() to use mesa_image_arg           GDB
17 *               * Add checksum to mesa_read_row()                         GDB
18 *               * Add return with number of bytes to mesa_read_image()    GDB
19 *                                                                         GDB
20 * $Id: mesalib.c 9330 2006-10-14 11:54:47Z hun $
21 */
22 #include "config.h"
23
24 #include "mesalib.h"
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <sys/time.h>
30 #include <string.h>
31
32 #include <gphoto2/gphoto2.h>
33 #include "gphoto2-endian.h"
34
35 #define GP_MODULE "dimera"
36 #define debuglog(e) GP_DEBUG( "%s", (e))
37
38 #ifdef CONVERT_PIXELS
39 static const uint16_t   pixelTable[256] = {
40         0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
41         0x008, 0x009, 0x00A, 0x00B, 0x00C, 0x00D, 0x00E, 0x00F,
42         0x010, 0x011, 0x012, 0x013, 0x014, 0x015, 0x016, 0x017,
43         0x018, 0x019, 0x01A, 0x01B, 0x01C, 0x01D, 0x01E, 0x01F,
44         0x020, 0x021, 0x022, 0x023, 0x024, 0x025, 0x026, 0x027,
45         0x028, 0x029, 0x02A, 0x02B, 0x02C, 0x02D, 0x02E, 0x02F,
46         0x030, 0x031, 0x032, 0x033, 0x034, 0x035, 0x036, 0x037,
47         0x038, 0x039, 0x03A, 0x03B, 0x03C, 0x03D, 0x03E, 0x03F,
48         0x040, 0x041, 0x042, 0x043, 0x044, 0x045, 0x046, 0x047,
49
50         0x048, 0x049, 0x04A, 0x04B, 0x04C, 0x04E, 0x04F, 0x050,
51         0x051, 0x052, 0x053, 0x054, 0x055, 0x056, 0x057, 0x058,
52         0x059, 0x05A, 0x05B, 0x05C, 0x05D, 0x05E, 0x05F, 0x060,
53         0x061, 0x062, 0x063, 0x064, 0x066, 0x067, 0x068, 0x069,
54         0x06A, 0x06C, 0x06D, 0x06E, 0x06F, 0x070, 0x072, 0x073,
55         0x074, 0x075, 0x076, 0x077, 0x078, 0x079, 0x07A, 0x07B,
56         0x07C, 0x07E, 0x07F, 0x081, 0x082, 0x084, 0x085, 0x087,
57
58         0x088, 0x08A, 0x08B, 0x08C, 0x08E, 0x08F, 0x090, 0x092,
59         0x093, 0x094, 0x096, 0x098, 0x09A, 0x09C, 0x09E, 0x0A0,
60         0x0A2, 0x0A3, 0x0A5, 0x0A6, 0x0A8, 0x0A9, 0x0AB, 0x0AC,
61         0x0AE, 0x0B0, 0x0B2, 0x0B4, 0x0B6, 0x0B8, 0x0BA, 0x0BC,
62
63         0x0BE, 0x0C0, 0x0C2, 0x0C4, 0x0C6, 0x0C8, 0x0CA, 0x0CD,
64         0x0CF, 0x0D2, 0x0D5, 0x0D8, 0x0DB, 0x0DE, 0x0E0, 0x0E2,
65         0x0E5, 0x0E7, 0x0EA, 0x0EC, 0x0EE, 0x0F1, 0x0F3, 0x0F6,
66         0x0FC, 0x102, 0x106, 0x10A, 0x10E, 0x111, 0x114, 0x117,
67
68         0x11A, 0x11D, 0x120, 0x123, 0x126, 0x12C, 0x132, 0x138,
69         0x13E, 0x142, 0x146, 0x14A, 0x150, 0x156, 0x15A, 0x15E,
70         0x162, 0x166, 0x16A, 0x16E, 0x17A, 0x180, 0x186, 0x18C,
71         0x192, 0x19E, 0x1AA, 0x1B0, 0x1B6, 0x1BA, 0x1BE, 0x1C2,
72
73         0x1C8, 0x1CE, 0x1DA, 0x1E6, 0x1F2, 0x1FE, 0x204, 0x20A,
74         0x216, 0x222, 0x22E, 0x23A, 0x240, 0x246, 0x24C, 0x252,
75
76         0x25E, 0x26A, 0x276, 0x282, 0x28E, 0x2A6, 0x2B2, 0x2BE,
77         0x2D6, 0x2EE, 0x2FA, 0x312, 0x336, 0x34E, 0x35e, 0x366
78 };
79 #endif
80
81 /*
82  * return the difference in tenths of seconds, between t1 and t2.
83  */
84 static long
85 timediff( struct timeval *t1, struct timeval *t2 )
86 {
87         long    t;
88
89         t = (t1->tv_sec - t2->tv_sec) * 10;
90         t += (t1->tv_usec - t2->tv_usec) / 100000;
91         return t;
92 }
93
94 /* flush input.  Wait for timeout deci-seconds to pass without input */
95
96 void
97 mesa_flush( GPPort *port, int timeout )
98 {
99         uint8_t b[256];
100         struct timeval  start, now;
101
102         gettimeofday( &start, NULL );
103
104         /* Clear any pending input bytes */
105         gp_port_flush(port, 0);
106
107         /* Wait for silence */
108         do {
109                 if ( gp_port_read( port, b, sizeof( b ) ) > 0 )
110                         /* reset timer */
111                         gettimeofday( &start, NULL );
112                 gettimeofday( &now, NULL );
113         } while ( timeout > timediff( &now, &start ) );
114         return;
115 }
116
117 /* Read exactly this number of bytes from the port within the given timeouts */
118 int
119 mesa_read( GPPort *port, uint8_t *b, int s, int timeout2, int timeout1 )
120 {
121         int             n = 0;
122         int             r, t;
123         struct timeval  start, now;
124
125         t = timeout1 ? timeout1 : timeout2;     /* set first byte timeout */
126         gettimeofday( &start, NULL );
127
128         do
129         {
130                 /* limit reads to 1k segment */
131                 r = gp_port_read( port, &b[n], s>1024?1024:s );
132                 if ( r > 0 )
133                 {
134                         n += r;
135                         s -= r;
136                         gettimeofday( &start, NULL );
137                         t = timeout2;
138                 }
139                 gettimeofday( &now, NULL );
140         } while ( s > 0 && t > timediff( &now, &start ) );
141         return n;
142 }
143
144 /* Send a command to the camera and read the acknowledgement byte */
145 int
146 mesa_send_command( GPPort *port, uint8_t *cmd, int n, int ackTimeout )
147 {
148         uint8_t c;
149
150         CHECK (gp_port_write( port, cmd, n ));
151
152         if ( mesa_read( port, &c, 1, ackTimeout, 0 ) != 1 )
153         {
154                 debuglog("mesa_send_command: timeout");
155                 return GP_ERROR_TIMEOUT;
156         }
157         if ( c != CMD_ACK )
158         {
159                 debuglog("mesa_send_command: error response");
160                 return GP_ERROR_CORRUPTED_DATA;
161         }
162         return GP_OK;
163 }
164
165 /* Open the serial port and configure it */
166 int
167 mesa_port_open( GPPort *port )
168 {
169         GPPortSettings settings;
170
171         debuglog("mesa_port_open()");
172         gp_port_set_timeout(port, 5000);
173
174         gp_port_get_settings(port, &settings);
175
176         settings.serial.speed   = 115200;
177         settings.serial.bits    = 8;
178         settings.serial.parity  = 0;
179         settings.serial.stopbits= 1;
180
181         return gp_port_set_settings(port, settings);
182 }
183
184 /* Close the serial port (now done by gphoto2 itself) */
185 int
186 mesa_port_close( GPPort *port )
187 {
188         return GP_OK;
189 }
190
191 /* reset camera */
192 int
193 mesa_reset( GPPort *port )
194 {
195         return gp_port_send_break( port, 1 );
196 }
197
198 /* set camera serial port speed, then our local port speed */
199 int
200 mesa_set_speed( GPPort *port, int speed )
201 {
202         uint8_t b[2];
203         gp_port_settings settings;
204
205         if (speed == 0)
206                 speed = 115200;         /* use default speed */
207
208         GP_DEBUG( 
209          "mesa_set_speed: speed %d", speed);
210
211         b[0] = SET_SPEED;
212
213         switch( speed )
214         {
215         case 9600:
216                 b[1] = 1;
217                 break;
218         case 14400:
219                 b[1] = 2;
220                 break;
221         case 19200:
222                 b[1] = 3;
223                 break;
224         case 38400:
225                 b[1] = 4;
226                 break;
227         case 57600:
228                 b[1] = 5;
229                 break;
230         case 76800:
231                 b[1] = 6;
232                 break;
233         case 115200:
234                 b[1] = 7;
235                 break;
236         case 230400:
237                 b[1] = 8;
238                 break;
239         case 460800:
240                 b[1] = 9;
241                 break;
242         default:
243                 return GP_ERROR_BAD_PARAMETERS;
244         }
245         CHECK (mesa_send_command( port, b, sizeof( b ), 10 ));
246
247         gp_port_get_settings(port, &settings);
248         settings.serial.speed = speed;
249         return gp_port_set_settings(port, settings);
250 }
251
252 /* get camera version number */
253 int
254 mesa_version( GPPort *port, char *version_string)
255 {
256         uint8_t         b;
257         uint8_t         r[3];
258         int             i;
259         char            *v = version_string;
260
261         b = MESA_VERSION;
262
263         CHECK (mesa_send_command( port, &b, 1, 10 ));
264
265         if ( ( i = mesa_read( port, r, sizeof( r ), 10, 0 ) ) != sizeof( r ) )
266         {
267                 return GP_ERROR_TIMEOUT;
268         }
269
270         GP_DEBUG( 
271          "mesa_version: %02x:%02x:%02x\n", r[0], r[1], r[2] );
272         sprintf(v, "%2x.%02x%c", r[1], r[0], r[2]);
273         /* highest byte must be < MESA_VERSION_SZ */
274         return GP_OK;
275 }
276
277 /* test camera serial port transmit */
278 int
279 mesa_transmit_test( GPPort *port )
280 {
281         uint8_t         b;
282         uint8_t         r[256];
283         unsigned int    i;
284
285         b = XMIT_TEST;
286
287         CHECK (mesa_send_command( port, &b, 1, 10 ));
288
289         if ( mesa_read( port, r, sizeof( r ), 10, 0 ) != sizeof( r ) )
290         {
291                 return GP_ERROR_TIMEOUT;
292         }
293
294         for ( i = 0; i < 256; i++ )
295         {
296                 if ( r[i] != i )
297                         return GP_ERROR_CORRUPTED_DATA;
298         }
299         return GP_OK;
300 }
301
302 /* test camera ram */
303 int
304 mesa_ram_test( GPPort *port )
305 {
306         uint8_t b;
307         uint8_t r;
308
309         b = RAM_TEST;
310
311         CHECK (mesa_send_command( port, &b, 1, 100 ));
312
313         if ( mesa_read( port, &r, 1, 10, 0 ) != 1 )
314         {
315                 return GP_ERROR_TIMEOUT;
316         }
317
318         return (int)r;
319 }
320
321 /*
322  * Read image row from camera.
323  * ********************************************************************   GDB
324  * *   The following contradicted by traces from my Win98 twain driver*   GDB
325  * ********************************************************************   GDB
326  * The image is stored in the camera as 504 row (0 - 503), the first 8 and the
327  * last 2 are blank. 
328  * The rows are 18 dummy pixels, 2 blanks, 646 pixels, 13 bytes garbage,
329  * 2 bytes blanks
330  *
331  * start  - offset into row;
332  * send   - bytes to send;
333  * skip   - bytes to skip;
334  * repeat - # repeats of send skip
335  * 640 bytes start = 28, send = 2, skip = 0, repeat = 320
336  * 320 bytes start = 28, send = 2, skip = 2, repeat = 160
337  *
338  * return number of bytes read, or < 0 if an error was detected.
339  *                                                                        GDB
340  * ********************************************************************   GDB
341  *                                                                        GDB
342  * 640 bytes start = 30, send = 4, skip = 0, repeat = 160                 GDB
343  * 320 bytes start = 30, send = 4, skip = 0, repeat = 80                  GDB
344  *                                                                        GDB
345  * return value >0 number of bytes read                                   GDB
346  *               GP_ERROR_TIMEOUT read time-out
347  *               GP_ERROR_BAD_PARAMETERS bad values
348  *               GP_ERROR command failure
349  *               GP_ERROR_CORRUPTED_DATA checksum failure
350  */
351
352 int                                                                     /*GDB*/
353 mesa_read_row( GPPort *port, uint8_t *r, struct mesa_image_arg *s )     /*GDB*/
354 {
355         uint8_t         b[9];
356         unsigned int    bytes, i;                                       /*GDB*/
357         uint8_t         checksum = 0;                                   /*GDB*/
358
359         if ( (bytes = s->send * s->repeat) > 680 )                      /*GDB*/
360         {
361                 return GP_ERROR_BAD_PARAMETERS;
362         }
363
364         b[0] = SEND_RAM;
365         htole16a(&b[1], s->row);
366         htole16a(&b[3], s->start);
367         b[5] = s->send;
368         b[6] = s->skip;
369         htole16a(&b[7], s->repeat);
370
371         CHECK (mesa_send_command( port, b, sizeof( b ), 10 ));
372
373 /*      return ( mesa_read( port, r, n, 10, 0 ));                         GDB*/
374         if ( mesa_read( port, r, bytes, 10, 0 ) != bytes )              /*GDB*/
375         {                                                               /*GDB*/
376                 return GP_ERROR_TIMEOUT;
377         }                                                               /*GDB*/
378                                                                         /*GDB*/
379         if ( mesa_read( port, b, 1, 10, 0 ) != 1)                       /*GDB*/
380         {                                                               /*GDB*/
381                 return GP_ERROR_TIMEOUT;
382         }                                                               /*GDB*/
383                                                                         /*GDB*/
384         for (i = 0; i < bytes; i++ )                                    /*GDB*/
385         {                                                               /*GDB*/
386                 checksum += r[i];                                       /*GDB*/
387         }                                                               /*GDB*/
388                                                                         /*GDB*/
389         if ( checksum != b[0] )                                         /*GDB*/
390         {                                                               /*GDB*/
391                 return GP_ERROR_CORRUPTED_DATA;
392         }                                                               /*GDB*/
393                                                                         /*GDB*/
394         return bytes;                                                   /*GDB*/
395 }
396
397 /*
398  * Snaps a full resolution image, with no flash, or shutter click
399  *
400  * exposure is in units of 1/50000 seconds
401  */
402 int
403 mesa_snap_image( GPPort *port, uint16_t exposure )
404 {
405         uint8_t         b[3];
406         int             timeout;
407
408         if ( exposure )
409                 timeout = (exposure/50000) + 10;
410         else
411                 timeout = 10;
412
413         b[0] = SNAP_IMAGE;
414         htole16a(&b[1], exposure);
415         return mesa_send_command( port, b, sizeof( b ), timeout );
416 }
417
418 /* return black levels, overwrites image memory */
419 int
420 mesa_black_levels( GPPort *port, uint8_t r[2] )
421 {
422         uint8_t b;
423
424         b = SND_BLACK;
425
426         CHECK (mesa_send_command( port, &b, 1, 10 ));
427
428         return mesa_read( port, r, 2, 10, 0 );
429 }
430
431 /*
432  * snap a view finder image, optionally return image in buffer.
433  *
434  * if hi_res is true, image is 128x96 packed 4 bits per pixel (6144 bytes).
435  * else               image is 64x48 packed 4 bits per pixel (1536 bytes).
436  *
437  * the image can be full scale, 0, zoom 2x 1, zoom 4x, 2, and for
438  * low res images, 8x, 3.
439  *
440  * row and column may be offset 0-197 and 0-223 for zoom. 
441  *
442  * exposure is * 1/50000 seconds.
443  *
444  * download specifies how, of if thge image is downloaded.
445  * 0-47         returns one 32 byte (64 pixel) row.
446  * 128-223      returns on 64 byte row.
447  * 249          returns all odd rows of a hi-res image 1536 bytes.
448  * 250          returns all even rows of a hi-res image 1536 bytes.
449  * 251          returns complete hi res image 6144 bytes.
450  * 252          returns nothing.
451  * 253          returns all odd rows of low res image 768 bytes.
452  * 254          returns all even rows of low res image 768 bytes.
453  * 255          returns entire image of 1536 bytes.
454  *
455  */
456 int
457 mesa_snap_view( GPPort *port, uint8_t *r, unsigned int hi_res,
458         unsigned int zoom, unsigned int row, unsigned int col, uint16_t exposure,
459         uint8_t download )
460 {
461         unsigned int    timeout, i;
462         unsigned int    bytes = 0;
463         uint8_t         b[7], cksum;
464
465         if ( download <= 47 )
466                 bytes = 32;
467         else if ( download >= 48 && download <= 127 )
468                 return GP_ERROR_BAD_PARAMETERS;
469         else if ( download >= 128 && download <= 223 )
470                 bytes = 64;
471         else if ( download >= 224 && download <= 248 )
472                 return GP_ERROR_BAD_PARAMETERS;
473         else if ( download == 249 || download == 250 )
474                 bytes = 1536;
475         else if ( download == 251 ) 
476                 bytes = 6144;
477         else if ( download == 252 )
478                 bytes = 0;
479         else if ( download == 253 || download == 254 )
480                 bytes = 768;
481         else /* if ( download == 255 ) */
482                 bytes = 1536;
483
484         if ( bytes != 0 && r == NULL )
485         {
486                 return GP_ERROR_BAD_PARAMETERS;
487         }
488
489         if ( exposure )
490                 timeout = (exposure/50000) + 10;
491         else
492                 timeout = 10;
493
494         b[0] = SNAP_VIEW;
495         b[1] = (zoom&3)+(hi_res?0x80:0);
496         b[2] = row;
497         b[3] = col;
498         htole16a(&b[4], exposure);
499         b[6] = download;
500
501         CHECK (mesa_send_command( port, b, sizeof( b ), timeout ));
502
503         if ( bytes != 0 )
504         {
505                 if ( mesa_read( port, r, bytes, 10, 0 ) != bytes )
506                 {
507                         return GP_ERROR_TIMEOUT;
508                 }
509
510                 if ( mesa_read( port, b, 1, 10, 0 ) != 1 )
511                 {
512                         return GP_ERROR_TIMEOUT;
513                 }
514
515                 for ( i = 0, cksum = 0; i < bytes; i++ )
516                 {
517                         cksum += r[i];
518                 }
519                 if ( cksum != b[0] )
520                 {
521                         return GP_ERROR_CORRUPTED_DATA;
522                 }
523         }
524         
525         return bytes;
526 }
527
528 /*
529  * tell camera to insert extra stop bits between bytes.
530  * slows down transmission without using a slower speed.
531  */
532 int
533 mesa_set_stopbits( GPPort *port, unsigned int bits )
534 {
535         uint8_t b[2];
536
537         b[0] = XTRA_STP_BIT;
538         b[1] = bits;
539
540         return mesa_send_command( port, b, sizeof( b ), 10 );
541 }
542
543 /* download viewfinder image ( see mesa_snap_view ) */
544 int
545 mesa_download_view( GPPort *port, uint8_t *r, uint8_t download )
546 {
547         unsigned int    bytes, i;
548         uint8_t         b[2], cksum;
549
550         if ( download <= 47 )
551                 bytes = 32;
552         else if ( download >= 48 && download <= 127 )
553                 return GP_ERROR_BAD_PARAMETERS;
554         else if ( download >= 128 && download <= 223 )
555                 bytes = 64;
556         else if ( download >= 224 && download <= 248 )
557                 return GP_ERROR_BAD_PARAMETERS;
558         else if ( download == 249 )
559                 bytes = 1536;
560         else if ( download == 250 || download == 251 ) 
561                 bytes = 768;
562         else if ( download == 252 )
563                 bytes = 0;
564         else if ( download == 253 )
565                 bytes = 6144;
566         else /* if ( download == 254 || download == 255 ) */
567                 bytes = 1536;
568
569         if ( bytes != 0 && r == NULL )
570         {
571                 return GP_ERROR_BAD_PARAMETERS;
572         }
573
574         b[0] = SND_VIEW;
575         b[1] = download;
576
577         CHECK (mesa_send_command( port, b, sizeof( b ), 10 ));
578
579         if ( bytes != 0 )
580         {
581                 if ( mesa_read( port, r, bytes, 10, 0 ) != bytes )
582                 {
583                         return GP_ERROR_TIMEOUT;
584                 }
585
586                 if ( mesa_read( port, b, 1, 10, 0 ) != 1 )
587                 {
588                         return GP_ERROR_TIMEOUT;
589                 }
590
591                 for ( i = 0, cksum = 0; i < bytes; i++ )
592                 {
593                         cksum += r[i];
594                 }
595                 if ( cksum != b[0] )
596                         return GP_ERROR_CORRUPTED_DATA;
597         }
598         
599         return bytes;
600 }
601
602 /*
603  * take a picture, with flash and shutter click
604  */
605 int
606 mesa_snap_picture( GPPort *port, uint16_t exposure )
607 {
608         unsigned int    timeout;
609         uint8_t         b[3];
610
611         if ( exposure )
612                 timeout = (exposure/50000) + 10;
613         else
614                 timeout = 10;
615
616         b[0] = SNAP_PICTURE;
617         htole16a(&b[1], exposure);
618
619         return mesa_send_command( port, b, sizeof( b ), timeout );
620 }
621
622 /* Get the camera chipset identification */
623 int
624 mesa_send_id( GPPort *port, struct mesa_id *id )
625 {
626         uint8_t         b, r[4];
627
628         b = SND_ID;
629
630         CHECK (mesa_send_command( port, &b, 1, 10 ));
631
632         if ( mesa_read( port, r, sizeof( r ), 10, 0 ) != sizeof( r ) )
633         {
634                 return GP_ERROR_TIMEOUT;
635         }
636
637         id->man = r[0] + ((r[1]&15)<<8);
638         id->ver = r[1]>>4;
639         id->year = 1996 + r[2];
640         id->week = r[3];
641
642         return GP_OK;
643 }
644
645 /*
646  * check for a camera, or a modem, send AT, if the response is 0x21,
647  * it is a camera, if it is "AT" it's a modem.
648  *
649  * returns       GP_OK = camera
650  *               GP_ERROR_MODEL_NOT_FOUND = modem
651  *               other = error
652  */
653 int
654 mesa_modem_check( GPPort *port )
655 {
656         uint8_t         b[3];
657
658         b[0] = 'A';
659         b[1] = 'T';
660         b[2] = '\r';
661
662         CHECK (gp_port_write( port, b, sizeof( b ) ));
663
664         /* Expect at least one byte */
665         if ( mesa_read( port, b, 1, 5, 0 ) < 1 )
666         {
667                 return GP_ERROR_TIMEOUT;
668         }
669
670         if ( b[0] == CMD_ACK )
671                 return GP_OK;
672
673         /* Anything past this point results in an error */
674         if ( mesa_read( port, b+1, sizeof(b) - 1, 2, 2 ) == sizeof(b) - 1 )
675         {
676                 if ( b[0] == 'A' && b[1] == 'T' )
677                 {
678                         mesa_flush( port, 10 );
679                         return GP_ERROR_MODEL_NOT_FOUND;
680                 }
681         }
682
683         mesa_flush( port, 10 );
684         return GP_ERROR;
685 }
686
687 /*
688  * mesa_read_image      - returns all or part of an image in the supplied buffer
689  *      uint8_t         *r, buffer to return image in.
690  *      struct mesa_image_arg   *i, download specifier.
691  *
692  *      return value    >0 number of bytes read
693  *                      GP_ERROR_TIMEOUT read time-out
694  *                      GP_ERROR command failure
695  *                      GP_ERROR_CORRUPTED_DATA checksum failure
696  */
697
698 int
699 mesa_read_image( GPPort *port, uint8_t *r, struct mesa_image_arg *s )
700 {
701         uint8_t         b[14];
702         unsigned long   bytes, i;
703         uint8_t         checksum = 0;
704
705         bytes = s->row_cnt * (s->repeat * s->send);
706
707         b[0]  = SND_IMAGE;
708         htole16a(&b[1], s->row);
709         htole16a(&b[3], s->start);
710         b[5]  = s->send;
711         b[6]  = s->skip;
712         htole16a(&b[7], s->repeat);
713         b[9]  = s->row_cnt;
714         b[10] = s->inc1;
715         b[11] = s->inc2;
716         b[12] = s->inc3;
717         b[13] = s->inc4;
718
719         CHECK (mesa_send_command( port, b, sizeof( b ), 10 ));
720
721         if ( mesa_read( port, r, bytes, 10, 0 ) != bytes )
722         {
723                 return GP_ERROR_TIMEOUT;
724         }
725
726         if ( mesa_read( port, b, 1, 10, 0 ) != 1 )
727         {
728                 return GP_ERROR_TIMEOUT;
729         }
730
731         for ( i = 0; i < bytes; i++ )
732         {
733                 checksum += r[ i ];
734         }
735
736         if ( checksum != b[0] )
737         {
738                 return GP_ERROR_CORRUPTED_DATA;
739         }
740
741         return bytes;
742 }
743
744 /*
745  * test serial link, send six bytes
746  *
747  * returns      GP_OK - success
748  *              GP_ERROR_TIMEOUT - no data received
749  *              GP_ERROR - command failed (no or bad ack)
750  *              GP_ERROR_CORRUPTED_DATA - returned bytes do not match
751  */
752 int
753 mesa_recv_test( GPPort *port, uint8_t r[6] )
754 {
755         uint8_t         b[7];
756         int             i;
757         
758         b[0] = RCV_TEST;
759         memcpy( &b[1], r, 6 );
760
761         CHECK (mesa_send_command( port, b, sizeof( b ), 10 ));
762
763         if ( mesa_read( port, r, 6, 10, 0 ) != 6 )
764         {
765                 return GP_ERROR_TIMEOUT;
766         }
767
768         for ( i = 0; i < 6; i++ )
769                 if ( r[i] != b[i+1] )
770                         return GP_ERROR_CORRUPTED_DATA;
771         return GP_OK;
772 }
773
774 /* Return the number of images in the EEPROM */
775 int
776 mesa_get_image_count( GPPort *port )
777 {
778         uint8_t         b;
779         uint8_t         r[2];
780
781         b = IMAGE_CNT;
782
783         CHECK (mesa_send_command( port, &b, 1, 10 ));
784
785         if ( mesa_read( port, r, sizeof( r ), 10, 0 ) != sizeof( r ) )
786         {
787                 return GP_ERROR_TIMEOUT;
788         }
789
790         return le16atoh(r);
791 }
792
793 /* load image from eeprom, into ram */
794 int
795 mesa_load_image( GPPort *port, int image )
796 {
797         uint8_t         b[3];
798
799         b[0] = LD_IMAGE;
800         htole16a(&b[1], image);
801
802         return mesa_send_command( port, b, sizeof( b ), 1000 );
803 }
804
805 /*
806  * Read EEPROM information
807  * Bytes 10..16 of info correspond to the Device ID field, bytes 45..51
808  */
809 int
810 mesa_eeprom_info( GPPort *port, int long_read, uint8_t info[MESA_EEPROM_SZ] )
811 {
812         uint8_t         b;
813
814         b = EEPROM_INFO;
815
816         CHECK (mesa_send_command( port, &b, 1, 10 ));
817
818         return mesa_read( port, info, long_read ? 49 : 33, 10, 0 );
819 }
820
821 /*
822  *
823  */
824
825 int32_t
826 mesa_read_thumbnail( GPPort *port, int picture, uint8_t *image )
827 {
828         uint8_t         b[3], checksum = 0;
829         uint32_t        bytes;
830         unsigned int    standard_res, i;
831
832         b[0] = SND_THUMB;
833         htole16a(&b[1], picture);
834
835         CHECK (mesa_send_command( port, b, sizeof( b ), 10 ));
836
837         if ( mesa_read( port, b, 3, 10, 0 ) != 3 )
838         {
839                 return GP_ERROR_TIMEOUT;
840         }
841
842         checksum = b[0] + b[1] + b[2];
843
844         standard_res = ((b[2] & 128) != 0);
845         bytes = b[0] + (b[1]<<8) + ((b[2] & 127)<<16);
846
847         if ( mesa_read( port, image, MESA_THUMB_SZ, 10, 0 ) != MESA_THUMB_SZ )
848         {
849                 return GP_ERROR_TIMEOUT;
850         }
851
852         if ( mesa_read( port, b, 1, 10, 0 ) != 1 )
853         {
854                 return GP_ERROR_TIMEOUT;
855         }
856
857         for ( i = 0; i < MESA_THUMB_SZ; i++ )
858         {
859                 checksum += image[i];
860         }
861
862         if ( checksum != b[0] )
863                 return GP_ERROR_CORRUPTED_DATA;
864
865         return (bytes + standard_res ? 0x1000000 : 0);
866 }
867
868 /* Return the camera's feature bits */
869 int
870 mesa_read_features( GPPort *port, struct mesa_feature *f )
871 {
872         uint8_t         b;
873
874         b = FEATURES;
875
876         CHECK (mesa_send_command( port, &b, 1, 10 ));
877
878         return ( mesa_read( port, (uint8_t *)f, sizeof( *f ), 10, 0 ) );
879 }
880
881 /* return percentage battery level */
882 int
883 mesa_battery_check( GPPort *port )
884 {
885         struct mesa_feature     f;
886         int                     l, r, rc;
887
888         if ( (rc = mesa_read_features( port, &f )) != sizeof( f ))
889         {
890                 return rc;
891         }
892
893         if ( (f.feature_bits_hi & BAT_VALID) == 0 )
894                 return GP_ERROR_MODEL_NOT_FOUND;
895
896         /* (df) Does BAT_DIGITAL need to be checked here? */
897
898         if ( ( l =  f.battery_level - f.battery_zero ) < 0 )
899                 l = 0;
900
901         r = f.battery_full - f.battery_zero;
902
903         return ( (l*100)/r );
904 }
905
906 int32_t
907 mesa_read_image_info( GPPort *port, int i, struct mesa_image_info *info )
908 {
909         uint8_t         b[3], r[3];
910         int32_t         bytes;
911         int32_t         standard_res;
912
913         b[0] = SND_IMG_INFO;
914         htole16a(&b[1], i);
915
916         CHECK (mesa_send_command( port, b, sizeof( b ), 10 ));
917
918         if ( mesa_read( port, r, sizeof( r ), 10, 0 ) != sizeof( r ) )
919         {
920                 return GP_ERROR_TIMEOUT;
921         }
922
923         standard_res = ((r[2] & 128) != 0);
924         bytes = r[0] + (r[1]<<8) + ((r[2] & 127)<<16);
925
926         if ( info != NULL )
927         {
928                 info->standard_res = standard_res;
929                 info->num_bytes = bytes;
930         }
931
932         return standard_res;
933 }
934
935 #ifdef CONVERT_PIXELS
936 /*
937  * return and image with raw pixels expanded.
938  */
939 uint16_t *
940 mesa_get_image( GPPort *port, int image )
941 {
942         static uint8_t                  buffer[640*480L];
943         static struct mesa_image_info   info;
944         static struct mesa_image_arg    ia;
945         uint8_t                         *b = buffer;
946         uint16_t                        *rbuffer;
947         int                             r, res;
948         unsigned long                   size, i;
949
950         if ( image != RAM_IMAGE_NUM )
951         {
952                 if ( mesa_load_image( port, image ) != GP_OK )
953                 {
954                         mesa_flush( port, 100 );
955                         return NULL;
956                 }
957
958                 if ( mesa_read_image_info( port, image, &info ) < 0 )
959                 {
960                         mesa_flush( port, 100 );
961                         return NULL;
962                 }
963                 if ( info.standard_res )
964                 {
965                         res = 1;
966                         size = 320*240;
967                 } else {
968                         res = 0;
969                         size = 640*480;
970                 }
971         } else {
972                 res = 0;
973                 size = 640*480;
974         }
975         rbuffer = (uint16_t *)malloc( size*(sizeof (uint16_t)) );
976         if ( rbuffer == NULL )
977                 return NULL;
978
979         ia.start = 28;
980         ia.send = 4;
981         ia.skip = 0;
982         ia.repeat = (res ? 80 : 160);
983         ia.row_cnt = 40;
984         ia.inc1 = 1;
985         ia.inc2 = 128;
986         ia.inc3 = ia.inc4 = 0;
987
988         for ( ia.row = 4; ia.row < (res ? 244 : 484) ; ia.row += ia.row_cnt )
989         {
990
991                 if ( (r = mesa_read_image( port, b, &ia )) < 0 )
992                 {
993                         free( rbuffer );
994                         return NULL;
995                 }
996                 b += r;
997         }
998
999         for ( i = 0; i < size; i++ )
1000         {
1001                 *rbuffer++ = pixelTable[*b++];
1002         }
1003
1004         return rbuffer;
1005 }
1006 #else
1007 /*
1008  * return and raw image retransmit on errors
1009  */
1010 uint8_t *
1011 mesa_get_image( GPPort *port, int image )
1012 {
1013         static struct mesa_image_info   info;
1014         static struct mesa_image_arg    ia;
1015         uint8_t                         *rbuffer, *b;
1016         int                             r, res, retry;
1017         unsigned long                   size;
1018
1019         if ( image != RAM_IMAGE_NUM )
1020         {
1021                 if ( mesa_load_image( port, image ) < 0 )
1022                 {
1023                         mesa_flush( port, 100 );
1024                         return NULL;
1025                 }
1026
1027                 if ( mesa_read_image_info( port, image, &info ) < 0 )
1028                 {
1029                         mesa_flush( port, 100 );
1030                         return NULL;
1031                 }
1032                 if ( info.standard_res )
1033                 {
1034                         res = 1;
1035                         size = 320*240;
1036                 } else {
1037                         res = 0;
1038                         size = 640*480;
1039                 }
1040         } else {
1041                 res = 0;
1042                 size = 640*480;
1043         }
1044         rbuffer = (uint8_t *)malloc( size );
1045         if ( rbuffer == NULL )
1046                 return NULL;
1047         b = rbuffer;
1048
1049         ia.start = 28;
1050         ia.send = 4;
1051         ia.skip = 0;
1052         ia.repeat = (res ? 80 : 160);
1053         ia.row_cnt = 40;
1054         ia.inc1 = 1;
1055         ia.inc2 = 128;
1056         ia.inc3 = ia.inc4 = 0;
1057
1058         for ( ia.row = 4; ia.row < (res ? 244 : 484) ; ia.row += ia.row_cnt )
1059         {
1060
1061                 for ( retry = 10;; )
1062                 {
1063                         if ( (r = mesa_read_image( port, b, &ia )) > 0)
1064                                 break;
1065
1066                                 /* if checksum error count retries */
1067                         if ( r == -2  && --retry > 0)
1068                                 continue;       /* not exceeded, try again */
1069
1070                                 /* error, exit */
1071                         free( rbuffer );
1072                         return NULL;
1073
1074                 }
1075                 b += r;
1076         }
1077
1078         return rbuffer;
1079 }
1080 #endif