Remove generated files
[framework/connectivity/libgphoto2.git] / camlibs / ricoh / ricoh.c
1 /* ricoh.c
2  *
3  * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, 
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details. 
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22 #include "ricoh.h"
23
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <gphoto2/gphoto2-port-log.h>
28
29 #include "crctab.h"
30
31 #define GP_MODULE "ricoh"
32
33 #define STX 0x02 /* start of text */
34 #define ETX 0x03 /* end of text */
35 #define ACK 0x06 /* acknowledge */
36 #define NAK 0x15 /* negative acknowledge */
37 #define ETB 0x17 /* end of transmission block */
38 #define DLE 0x10 /* datalink escape */
39
40 #ifdef ENABLE_NLS
41 #  include <libintl.h>
42 #  undef _
43 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
44 #  ifdef gettext_noop
45 #    define N_(String) gettext_noop (String)
46 #  else
47 #    define N_(String) (String)
48 #  endif 
49 #else
50 #  define textdomain(String) (String)
51 #  define gettext(String) (String)
52 #  define dgettext(Domain,Message) (Message)
53 #  define dcgettext(Domain,Message,Type) (Message)
54 #  define bindtextdomain(Domain,Directory) (Domain)
55 #  define _(String) (String)
56 #  define N_(String) (String)
57 #endif
58
59 #define CR(result)       {int r_mac=(result); if (r_mac<0) return r_mac;}
60 #define CRF(result,data) {int r_mac=(result); \
61   if (r_mac<0) {free (data); return r_mac;}}
62
63 #define C_CMD(context,cmd,target)                       \
64 {                                                       \
65         if (cmd != target) {                            \
66                 gp_context_error (context, _("Expected %i, got %i. Please "\
67                         "report this error to %s."),\
68                         cmd, target, MAIL_GPHOTO_DEVEL);                        \
69                 return (GP_ERROR_CORRUPTED_DATA);       \
70         }                                               \
71 }
72 #define C_LEN(context,len,target)                       \
73 {                                                       \
74         if (len != target) {                            \
75                 gp_context_error (context, _("Expected "\
76                         "%i bytes, got %i. "            \
77                         "Please report this error to "  \
78                         "%s."), \
79                         target, len, MAIL_GPHOTO_DEVEL);                        \
80                 return (GP_ERROR_CORRUPTED_DATA);       \
81         }                                               \
82 }
83
84 #ifndef HAVE_TM_GMTOFF
85 /* required for time conversions in canon_int_set_time() */
86 extern long int timezone;
87 #endif
88
89 static int
90 ricoh_send (Camera *camera, GPContext *context, unsigned char cmd,
91             unsigned char number,
92             const unsigned char *data, unsigned char len)
93 {
94         unsigned char buf[6];
95         unsigned int i, w, crc = 0;
96         int timeout;
97
98         /* First, make sure there is no data coming from the camera. */
99         CR (gp_port_get_timeout (camera->port, &timeout));
100         CR (gp_port_set_timeout (camera->port, 20));
101         while (gp_port_read (camera->port, buf, 1) >= 0);
102         CR (gp_port_set_timeout (camera->port, timeout));
103
104         /* Write header */
105         buf[0] = DLE;
106         buf[1] = STX;
107         buf[2] = cmd;
108         buf[3] = len;
109         CR (gp_port_write (camera->port, buf, 4));
110         crc = updcrc (cmd, crc);
111         crc = updcrc (len, crc);
112
113         /*
114          * Write data (escape DLE).
115          *
116          * w ... bytes written
117          */
118         w = 0;
119         while (w < len) {
120                 for (i = w; i < len; i++) {
121                         crc = updcrc (data[i], crc);
122                         if (data[i] == 0x10) {
123                                 i++;
124                                 break;
125                         }
126                 }
127                 CR (gp_port_write (camera->port, data + w, i - w));
128                 if (data[i - 1] == 0x10)
129                         CR (gp_port_write (camera->port, "\x10", 1));
130                 w = i;
131         }
132
133         /* Write footer */
134         buf[0] = DLE;
135         buf[1] = ETX;
136         buf[2] = crc >> 0;
137         buf[3] = crc >> 8;
138         buf[4] = len + 2;
139         buf[5] = number;
140         CR (gp_port_write (camera->port, buf, 6));
141
142         return (GP_OK);
143 }
144
145 static int
146 ricoh_send_ack (Camera *camera, GPContext *context)
147 {
148         CR (gp_port_write (camera->port, "\x10\x06", 2));
149         return (GP_OK);
150 }
151
152 static int
153 ricoh_send_nack (Camera *camera, GPContext *context)
154 {
155         CR (gp_port_write (camera->port, "\x10\x15", 2));
156         return (GP_OK);
157 }
158
159 static int
160 ricoh_recv (Camera *camera, GPContext *context, unsigned char *cmd,
161             unsigned char *number, unsigned char *data, unsigned char *len)
162 {
163         unsigned char buf[6];
164         unsigned char r, i, ii, last_dle;
165         unsigned int crc = 0;
166
167         for (ii = 0; ; ii++) {
168                 crc = 0;
169
170                 /*
171                  * Get header (DLE,STX). If we receive (DLE,ACK), just
172                  * drop that and read on.
173                  */
174                 for (i = 0, buf[1] = ACK; i < 4; i++) {
175                         CR (gp_port_read (camera->port, buf, 2));
176                         if (buf[0] != DLE) {
177                                 gp_context_error (context, _("We expected "
178                                         "0x%x but received 0x%x. Please "
179                                         "contact %s."),
180                                                 DLE, buf[0], MAIL_GPHOTO_DEVEL);
181                                 return (GP_ERROR_CORRUPTED_DATA);
182                         }
183                         if (buf[1] != ACK)
184                                 break;
185                 }
186                 switch (buf[1]) {
187                 case STX:
188                         break;
189                 case NAK:
190                 default:
191                         gp_context_error (context, _("We expected "
192                                 "0x%x but received 0x%x. Please "
193                                 "contact %s."),
194                                         STX, buf[1], MAIL_GPHOTO_DEVEL);
195                         return GP_ERROR_CORRUPTED_DATA;
196                 }
197
198                 CR (gp_port_read (camera->port, cmd, 1));
199                 CR (gp_port_read (camera->port, len, 1));
200                 crc = updcrc (*cmd, crc);
201                 crc = updcrc (*len, crc);
202
203                 /*
204                  * Get data (check for DLEs).
205                  * r ... number of bytes received
206                  */
207                 r = 0;
208                 last_dle = 0;
209                 while (r < *len) {
210                         CR (gp_port_read (camera->port, data + r, *len - r));
211                         if (last_dle) {
212                                 r++;
213                                 last_dle = 0;
214                         }
215                         for (i = r; i < *len; i++) {
216                                 if (data[r] == DLE) {
217                                         if (i + 1 != *len &&
218                                             data[r + 1] != DLE) {
219                                                 gp_context_error (context,
220                                                         _("Bad characters "
221                                                         "(0x%x, 0x%x). Please "
222                                                         "contact %s."),
223                                                         data[r], data[r + 1], MAIL_GPHOTO_DEVEL);
224                                                 return (GP_ERROR_CORRUPTED_DATA);
225                                         }
226                                         memmove (&data[r], &data[r +1],
227                                                  *len - i - 1);
228                                         i++;
229                                 }
230                                 crc = updcrc (data[r], crc);
231                                 if (i != *len)
232                                         r++;
233                                 else
234                                         last_dle = 1;
235                         }
236                 }
237
238                 /* Get footer */
239                 CR (gp_port_read (camera->port, buf, 6));
240
241                 if ((buf[0] != DLE) || (buf[1] != ETX && buf[1] != ETB))
242                         return (GP_ERROR_CORRUPTED_DATA);
243
244                 /* CRC correct? If not, retry. */
245                 if ((buf[2] != (crc & 0xff)) ||
246                     (buf[3] != (crc >> 8 & 0xff)) ||
247                     (buf[4] != *len + 2)) {
248                         GP_DEBUG ("CRC error. Retrying...");
249                         CR (ricoh_send_nack (camera, context));
250                         continue;
251                 }
252
253                 /* Acknowledge the packet. */
254                 CR (ricoh_send_ack (camera, context));
255
256                 /* If camera is busy, try again (but at most 4 times). */
257                 if ((*len == 3) && (data[0] == 0x00) &&
258                                    (data[1] == 0x04) &&
259                                    (data[2] == 0xff)) {
260                         if (ii >= 4) {
261                                 gp_context_error (context, _("Camera busy. "
262                                         "If the problem persists, please "
263                                         "contact %s."), MAIL_GPHOTO_DEVEL);
264                                 return (GP_ERROR);
265                         }
266                         continue;
267                 }
268
269                 /* Everything is ok. Break out of loop. */
270                 break;
271         }
272
273         /* Sequence number */
274         if (number)
275                 *number = buf[5];
276
277         return (GP_OK);
278 }
279
280 static int
281 ricoh_transmit (Camera *camera, GPContext *context, unsigned char cmd,
282                 const unsigned char *data, unsigned char len,
283                 unsigned char *ret_data, unsigned char *ret_len)
284 {
285         unsigned char ret_cmd;
286         unsigned int r = 0;
287         int result;
288  
289         while (1) {
290                 CR (ricoh_send (camera, context, cmd, 0, data, len));
291                 result = ricoh_recv (camera, context, &ret_cmd, NULL,
292                                      ret_data, ret_len);
293                 switch (result) {
294                 case GP_ERROR_TIMEOUT:
295                         if (++r > 2) {
296                                 gp_context_error (context, _("Timeout "
297                                         "even after 2 retries. Please "
298                                         "contact %s."), MAIL_GPHOTO_DEVEL);
299                                 return (GP_ERROR_TIMEOUT);
300                         }
301                         GP_DEBUG ("Timeout! Retrying...");
302                         continue;
303                 default:
304                         CR (result);
305                 }
306
307                 /* Check if the answer is for our command. */
308                 if (cmd != ret_cmd) {
309                         GP_DEBUG ("Commands differ (expected 0x%02x, "
310                                   "got 0x%02x)!", cmd, ret_cmd);
311                         if (++r > 2) {
312                                 gp_context_error (context, _("Communication "
313                                         "error even after 2 retries. Please "
314                                         "contact %s."), MAIL_GPHOTO_DEVEL);
315                                 return (GP_ERROR);
316                         }
317                         continue;
318                 }
319
320                 /* Check if the camera reported success. */
321                 if ((*ret_len >= 2) && (ret_data[0] == 0x00) &&
322                                        (ret_data[1] == 0x00))
323                         break;
324
325                 /* Check if the camera reported success, 2nd version. */
326                 if ((*ret_len == 3) && (ret_data[0] == 0x00) &&
327                                        (ret_data[1] == 0x06) &&
328                                        (ret_data[2] == 0xff))
329                         break;
330
331                 /* If camera is busy, try again (but at most 4 times). */
332                 if ((*ret_len == 3) && (ret_data[0] == 0x00) &&
333                                        (ret_data[1] == 0x04) &&
334                                        (ret_data[2] == 0xff)) {
335                         if (++r >= 4) {
336                                 gp_context_error (context, _("Camera busy. "
337                                         "If the problem persists, please "
338                                         "contact %s."), MAIL_GPHOTO_DEVEL);
339                                 return (GP_ERROR);
340                         }
341                         continue;
342                 }
343
344                 /*
345                  * It could be that the camera is in the wrong mode to
346                  * execute this command.
347                  */
348                 if ((*ret_len == 2) && (ret_data[0] == 0x06) &&
349                                        (ret_data[1] == 0x00)) {
350                         gp_context_error (context, _("Camera is in wrong "
351                                 "mode. Please contact "
352                                 "%s."), MAIL_GPHOTO_DEVEL);
353                         return (GP_ERROR);
354                 }
355
356                 /* Invalid parameters? */
357                 if ((*ret_len == 2) && (ret_data[0] == 0x04) &&
358                                        (ret_data[1] == 0x00)) {
359                         gp_context_error (context, _("Camera did not "
360                                 "accept the parameters. Please contact "
361                                 "%s."), MAIL_GPHOTO_DEVEL);
362                         return (GP_ERROR);
363                 }
364
365                 gp_context_error (context, _("An unknown error occurred. "
366                         "Please contact %s."), MAIL_GPHOTO_DEVEL);
367                 return (GP_ERROR);
368         }
369
370         /* Success! We don't need the first two bytes any more. */
371         *ret_len -= 2;
372         if (*ret_len > 0)
373                 memmove (ret_data, ret_data + 2, *ret_len);
374
375         return (GP_OK);
376 }
377
378 int
379 ricoh_get_pic_size (Camera *camera, GPContext *context, unsigned int n,
380                     unsigned long *size)
381 {
382         unsigned char p[3], buf[0xff], len;
383
384         GP_DEBUG ("Getting size of picture %i...", n);
385
386         p[0] = 0x04;
387         p[1] = n >> 0;
388         p[2] = n >> 8;
389         CR (ricoh_transmit (camera, context, 0x95, p, 3, buf, &len));
390         C_LEN (context, len, 4);
391
392         if (size)
393                 *size = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0] << 0;
394
395         return (GP_OK);
396 }
397
398 #define B2H( bcd ) ((bcd>>4)*10+(bcd&0xF))
399
400 int
401 ricoh_get_pic_date (Camera *camera, GPContext *context, unsigned int n,
402                     time_t *date)
403 {
404         unsigned char p[3], buf[0xff], len;
405         struct tm time;
406
407         GP_DEBUG ("Getting date of picture %i...", n);
408
409         p[0] = 0x03;
410         p[1] = n >> 0;
411         p[2] = n >> 8;
412         CR (ricoh_transmit (camera, context, 0x95, p, 3, buf, &len));
413         C_LEN (context, len, 7);
414
415         if (date) {
416                 time.tm_year = B2H (buf[1]);
417                 /* correct for Y2K in case older images are read */
418                 if (time.tm_year < 90) time.tm_year += 100;                     
419                 time.tm_mon  = B2H (buf[2]) - 1;
420                 time.tm_mday = B2H (buf[3]);
421                 time.tm_hour = B2H (buf[4]);
422                 time.tm_min  = B2H (buf[5]);
423                 time.tm_sec  = B2H (buf[6]);
424                 time.tm_isdst = -1;
425                 *date = mktime (&time);
426         }
427
428         return (GP_OK);
429 }
430
431 int
432 ricoh_get_pic_name (Camera *camera, GPContext *context, unsigned int n,
433                     const char **name)
434 {
435         unsigned char p[3], len;
436         static unsigned char buf[0xff];
437
438         GP_DEBUG ("Getting name of picture %i...", n);
439
440         p[0] = 0x00;
441         p[1] = n >> 0;
442         p[2] = n >> 8;
443         CR (ricoh_transmit (camera, context, 0x95, p, 3, buf, &len));
444
445         if (name && *name) {
446                 *name = buf;
447                 buf[len] = '\0';
448         }
449
450         return (GP_OK);
451 }
452
453 int
454 ricoh_get_pic_memo (Camera *camera, GPContext *context, unsigned int n,
455                     const char **memo)
456 {
457         unsigned char p[3], len;
458         static unsigned char buf[0xff];
459
460         GP_DEBUG ("Getting memo of picture %i...", n);
461
462         p[0] = 0x02;
463         p[1] = n >> 0;
464         p[2] = n >> 8;
465         CR (ricoh_transmit (camera, context, 0x95, p, 3, buf, &len));
466
467         if (memo && *memo) {
468                 *memo = buf;
469                 buf[len] = '\0';
470         }
471
472         return (GP_OK);
473 }
474
475 int
476 ricoh_del_pic (Camera *camera, GPContext *context, unsigned int n)
477 {
478         unsigned char p[2], buf[0xff], len;
479
480         GP_DEBUG ("Deleting picture %i...", n);
481
482         /* Put camera in delete mode */
483         CR (ricoh_transmit (camera, context, 0x97, NULL, 0, buf, &len));
484         C_LEN (context, len, 0);
485
486         /* Find and send picture to delete */
487         p[0] = n >> 0;
488         p[1] = n >> 8;
489         CR (ricoh_transmit (camera, context, 0x93, p, 2, buf, &len));
490         C_LEN (context, len, 0);
491         CR (ricoh_transmit (camera, context, 0x92, p, 2, buf, &len));
492         C_LEN (context, len, 0);
493
494         return (GP_OK);
495 }
496
497 int
498 ricoh_get_num (Camera *camera, GPContext *context, unsigned int *n)
499 {
500         unsigned char p[2], buf[0xff], len;
501
502         GP_DEBUG ("Getting number of pictures...");
503
504         p[0] = 0x00;
505         p[1] = 0x01;
506         CR (ricoh_transmit (camera, context, 0x51, p, 2, buf, &len));
507         C_LEN (context, len, 2);
508
509         if (n)
510                 *n = (buf[1] << 8) | buf[0];
511
512         return (GP_OK);
513 }
514
515 int
516 ricoh_set_speed (Camera *camera, GPContext *context, RicohSpeed speed)
517 {
518         unsigned char p[1], buf[0xff], len;
519
520         p[0] = speed;
521         CR (ricoh_transmit (camera, context, 0x32, p, 1, buf, &len));
522         C_LEN (context, len, 0);
523
524         /* Wait for camera to switch speed. */
525         sleep (1);
526
527         return (GP_OK);
528 }
529
530 int
531 ricoh_connect (Camera *camera, GPContext *context, RicohModel *model)
532 {
533         unsigned char p[3], buf[0xff], len;
534
535         p[0] = 0x00;
536         p[1] = 0x00;
537         p[2] = 0x00;
538         CR (ricoh_transmit (camera, context, 0x31, p, 3, buf, &len));
539         C_LEN (context, len, 4);
540
541         /* Model */
542         if (model)
543                 *model = (buf[0] << 8) | buf[1];
544
545         /* No idea what buf[2] and buf[3] contain. */
546
547         return (GP_OK);
548 }
549
550 int
551 ricoh_disconnect (Camera *camera, GPContext *context)
552 {
553         unsigned char buf[0xff], len;
554
555         CR (ricoh_transmit (camera, context, 0x37, NULL, 0, buf, &len));
556         C_LEN (context, len, 2);
557
558         return (GP_OK);
559 }
560
561 static unsigned char header[236] = {
562         0x49,0x49,0x2a,0x00,0x08,0x00,0x00,0x00,0x0c,0x00,0x00,0x01,0x03,0x00,
563         0x01,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x01,0x01,0x03,0x00,0x01,0x00,
564         0x00,0x00,0x3c,0x00,0x00,0x00,0x02,0x01,0x03,0x00,0x03,0x00,0x00,0x00,
565         0x9e,0x00,0x00,0x00,0x03,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
566         0x00,0x00,0x06,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
567         0x11,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0xec,0x00,0x00,0x00,0x15,0x01,
568         0x03,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x17,0x01,0x04,0x00,
569         0x01,0x00,0x00,0x00,0x80,0x25,0x00,0x00,0x1c,0x01,0x03,0x00,0x01,0x00,
570         0x00,0x00,0x01,0x00,0x00,0x00,0x11,0x02,0x05,0x00,0x03,0x00,0x00,0x00,
571         0xa4,0x00,0x00,0x00,0x12,0x02,0x03,0x00,0x02,0x00,0x00,0x00,0x02,0x00,
572         0x01,0x00,0x14,0x02,0x05,0x00,0x06,0x00,0x00,0x00,0xbc,0x00,0x00,0x00,
573         0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xe0,0xd0,0x22,0x13,
574         0x00,0x00,0x00,0x40,0x80,0x68,0x91,0x25,0x00,0x00,0x00,0x40,0xa8,0xc6,
575         0x4b,0x07,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
576         0x00,0x00,0xe0,0x1f,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x10,0x00,0x00,
577         0x20,0x00,0x00,0x00,0xe0,0x1f,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x10,
578         0x00,0x00,0x20,0x00,0x00,0x00,0xe0,0x1f,0x00,0x00,0x20,0x00
579 };
580
581 int
582 ricoh_get_pic (Camera *camera, GPContext *context, unsigned int n,
583                RicohFileType type, unsigned char **data, unsigned int *size)
584 {
585         unsigned char p[2], cmd, buf[0xff], len;
586         unsigned int r, header_len;
587         RicohMode mode;
588
589         GP_DEBUG ("Getting image %i as %s...", n, 
590                                                         (type==RICOH_FILE_TYPE_PREVIEW ? "thumbnail":"image"));
591         
592         /* Put camera into play mode, if not already */
593         CR (ricoh_get_mode (camera, context, &mode));
594         if (mode != RICOH_MODE_PLAY)
595             CR (ricoh_set_mode (camera, context, RICOH_MODE_PLAY));
596
597         /* Send picture number */
598         p[0] = n >> 0;
599         p[1] = n >> 8;
600         CR (ricoh_transmit (camera, context, (unsigned char) type,
601                             p, 2, buf, &len));
602         C_LEN (context, len, 16);
603
604         /*
605          * Allocate the necessary memory. Note that previews are 80x60 pixels
606          * raw TIFF data, we therefore need to allocate some extra memory
607          * for the TIFF header.
608          */
609         header_len = (type == RICOH_FILE_TYPE_PREVIEW) ? sizeof (header) : 0;
610         *size = buf[15] << 24 | buf[14] << 16 | buf[13] << 8 | buf[12];
611         *size += header_len;
612
613         *data = malloc (*size);
614         if (!*data)
615                 return (GP_ERROR_NO_MEMORY);
616
617         /*
618          * Receive data.
619          * r ... number of bytes received
620          */
621         for (r = 0; r < (*size) - header_len; r += len) {
622                 CRF (ricoh_recv (camera, context, &cmd, NULL,
623                                  *data + header_len + r, &len), *data);
624                 C_CMD (context, cmd, 0xa2);
625         }
626
627         /* In case of previews, copy over the TIFF header. */
628         if (type == RICOH_FILE_TYPE_PREVIEW)
629                 memcpy (*data, header, header_len);
630
631         return (GP_OK);
632 }
633
634 int
635 ricoh_get_date (Camera *camera, GPContext *context, time_t *date)
636 {
637         unsigned char p[1], buf[0xff], len;
638         struct tm time;
639
640         p[0] = 0x0a;
641         CR (ricoh_transmit (camera, context, 0x51, p, 1, buf, &len));
642
643         /* the camera only supplies 2 digits for year, so I will
644          * make the assumption that if less than 90, then it is
645          * year 2000 or greater */
646          time.tm_year = ((buf[1] & 0xf0) >> 4) * 10 + (buf[1] & 0xf);
647          if(time.tm_year < 90) time.tm_year += 100;
648          time.tm_mon =  ((buf[2] & 0xf0) >> 4) * 10 + (buf[2] & 0xf) - 1;
649          time.tm_mday = ((buf[3] & 0xf0) >> 4) * 10 + (buf[3] & 0xf);
650          time.tm_hour = ((buf[4] & 0xf0) >> 4) * 10 + (buf[4] & 0xf);
651          time.tm_min =  ((buf[5] & 0xf0) >> 4) * 10 + (buf[5] & 0xf);
652          time.tm_sec =  ((buf[6] & 0xf0) >> 4) * 10 + (buf[6] & 0xf);
653          time.tm_isdst = -1;
654          *date = mktime (&time);
655
656          return (GP_OK);
657 }
658
659 #ifdef HEX
660 #  undef HEX
661 #endif
662 #define HEX(x) (((x)/10)<<4)+((x)%10)
663
664 int
665 ricoh_set_date (Camera *camera, GPContext *context, time_t time)
666 {
667         unsigned char p[8], buf[0xff], len;
668         struct tm *t;
669
670         p[0] = 0x0a;
671
672         /* Call localtime() to get 'extern long timezone' */
673         t = localtime (&time);
674 #ifdef HAVE_TM_GMTOFF
675         time += t->tm_gmtoff;
676 #else  
677         time += timezone;
678 #endif 
679         t = localtime (&time);
680         GP_DEBUG ("ricoh_set_date: converted time to localtime %s "
681                   "(timezone is %ld)", asctime (t), timezone);
682
683         p[1] = HEX (t->tm_year / 100 + 19);
684         p[2] = HEX (t->tm_year % 100);
685         p[3] = HEX (t->tm_mon + 1);
686         p[4] = HEX (t->tm_mday);
687         p[5] = HEX (t->tm_hour);
688         p[6] = HEX (t->tm_min);
689         p[7] = HEX (t->tm_sec);
690         CR (ricoh_transmit (camera, context, 0x50, p, 8, buf, &len));
691
692         return (GP_OK);
693 }
694
695 /* get the cameras memory size */
696 int
697 ricoh_get_cam_mem (Camera *camera, GPContext *context, int *size)
698 {
699         unsigned char p[2], buf[0xff], len;
700
701         p[0] = 0x00;
702         p[1] = 0x05;
703         CR (ricoh_transmit (camera, context, 0x51, p, 2, buf, &len));
704         C_LEN (context, len, 4);
705
706         if (size)
707                 *size = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
708
709         return (GP_OK);
710 }
711
712 /* get the cameras available memory size */
713 int
714 ricoh_get_cam_amem (Camera *camera, GPContext *context, int *size)
715 {
716         unsigned char p[2], buf[0xff], len;
717
718         p[0] = 0x00;
719         p[1] = 0x06;
720         CR (ricoh_transmit (camera, context, 0x51, p, 2, buf, &len));
721         C_LEN (context, len, 4);
722
723         if (size)
724                 *size = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
725
726         return (GP_OK);
727 }
728
729 #define RICOH_GET_SET_VALUE(name,type,code)                             \
730 int                                                                     \
731 ricoh_get_##name (Camera *camera, GPContext *context,                   \
732                   type *value)                                          \
733 {                                                                       \
734         unsigned char p[1], buf[0xff], len;                             \
735                                                                         \
736         p[0] = (code);                                                  \
737         CR (ricoh_transmit (camera, context, 0x51, p, 1, buf, &len));   \
738         C_LEN (context, len, 1);                                        \
739         if (value)                                                      \
740                 *value = buf[0];                                        \
741         return (GP_OK);                                                 \
742 }                                                                       \
743                                                                         \
744 int                                                                     \
745 ricoh_set_##name (Camera *camera, GPContext *context,                   \
746                   type value)                                           \
747 {                                                                       \
748         unsigned char p[2], buf[0xff], len;                             \
749                                                                         \
750         p[0] = (code);                                                  \
751         p[1] = (unsigned char) value;                                   \
752         CR (ricoh_transmit (camera, context, 0x50, p, 2, buf, &len));   \
753         C_LEN (context, len, 0);                                        \
754                                                                         \
755         return (GP_OK);                                                 \
756 }
757
758 RICOH_GET_SET_VALUE(exposure,   RicohExposure,   0x03)
759 RICOH_GET_SET_VALUE(white_level,RicohWhiteLevel, 0x04)
760 RICOH_GET_SET_VALUE(zoom,       RicohZoom,       0x05)
761 RICOH_GET_SET_VALUE(flash,      RicohFlash,      0x06)
762 RICOH_GET_SET_VALUE(rec_mode,   RicohRecMode,    0x07)
763 RICOH_GET_SET_VALUE(compression,RicohCompression,0x08)
764 RICOH_GET_SET_VALUE(resolution, RicohResolution, 0x09)
765 RICOH_GET_SET_VALUE(mode,       RicohMode,       0x12)
766 RICOH_GET_SET_VALUE(macro,      RicohMacro,      0x16)
767
768 int
769 ricoh_get_copyright (Camera *camera, GPContext *context, const char **copyright)
770 {
771         unsigned char p[1], len;
772         static char buf[1024];
773
774         p[0] = 0x0f;
775         CR (ricoh_transmit (camera, context, 0x51, p, 1, buf, &len));
776
777         if (copyright && *copyright) {
778                 *copyright = buf;
779                 buf[len] = '\0';
780         }
781
782         return (GP_OK);
783 }
784
785 int
786 ricoh_set_copyright (Camera *camera, GPContext *context, const char *copyright)
787 {
788         unsigned char p[21], len, buf[0xff];
789
790         p[0] = 0x0f;
791         strncpy (p + 1, copyright, 20);
792         CR (ricoh_transmit (camera, context, 0x50, p, 21, buf, &len));
793
794         return (GP_OK);
795 }
796
797 int
798 ricoh_take_pic (Camera *camera, GPContext *context)
799 {
800         unsigned char p[1];
801         RicohMode mode;
802
803         /* Put camera into record mode, if not already */
804         CR (ricoh_get_mode (camera, context, &mode));
805         if (mode != RICOH_MODE_RECORD)
806                 CR (ricoh_set_mode (camera, context, RICOH_MODE_RECORD));
807
808         p[0] = 0x01;
809         CR (ricoh_send (camera, context, 0x60, 0x00, p, 1));
810
811         return (GP_OK);
812 }
813
814 #undef MIN
815 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
816
817 int
818 ricoh_put_file (Camera *camera, GPContext *context, const char *name,
819                 const unsigned char *data, unsigned int size)
820 {
821         RicohMode mode;
822         unsigned char p[16], len, buf[0xff], block[0xff];
823         unsigned int pic_num, i, pr;
824
825         CR (ricoh_get_mode (camera, context, &mode));
826         if (mode != RICOH_MODE_PLAY)
827                 CR (ricoh_set_mode (camera, context, RICOH_MODE_PLAY));
828
829         /* Filename ok? */
830         if (strlen (name) > 12) {
831                 gp_context_error (context, _("The filename's length must not "
832                         "exceed 12 characters ('%s' has %i characters)."),
833                         name, strlen (name));
834                 return (GP_ERROR);
835         }
836
837         strncpy (p, name, 12);
838         p[12] = size << 24;
839         p[13] = size << 16;
840         p[14] = size << 8;
841         p[15] = size;
842         CR (ricoh_transmit (camera, context, 0xa1, p, 16, buf, &len));
843         C_LEN (context, len, 2);
844
845         /*
846          * We just received the picture number of the new file. We don't 
847          * need it.
848          */
849         pic_num = buf[0] | (buf[1] << 8);
850
851         /* Now send the data */
852         pr = gp_context_progress_start (context, size, _("Uploading..."));
853         for (i = 0; i < size; i += 128) {
854                 memset (block, 0, sizeof (buf));
855                 memcpy (block, data + i, MIN (128, size - i));
856                 CR (ricoh_transmit (camera, context, 0xa2, block, 128, 
857                                     buf, &len));
858                 C_LEN (context, len, 0);
859                 if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL)
860                         return (GP_ERROR_CANCEL);
861                 gp_context_progress_update (context, pr, MIN (i + 128, size));
862         }
863         gp_context_progress_stop (context, pr);
864
865         /* Finish upload */
866         p[0] = 0x12;
867         p[1] = 0x00;
868         CR (ricoh_transmit (camera, context, 0x50, p, 2, buf, &len));
869         C_LEN (context, len, 0);
870
871         return (GP_OK);
872 }