3 * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
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.
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.
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.
27 #include <gphoto2/gphoto2-port-log.h>
31 #define GP_MODULE "ricoh"
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 */
43 # define _(String) dgettext (GETTEXT_PACKAGE, String)
45 # define N_(String) gettext_noop (String)
47 # define N_(String) (String)
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)
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;}}
63 #define C_CMD(context,cmd,target) \
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); \
72 #define C_LEN(context,len,target) \
74 if (len != target) { \
75 gp_context_error (context, _("Expected "\
76 "%i bytes, got %i. " \
77 "Please report this error to " \
79 target, len, MAIL_GPHOTO_DEVEL); \
80 return (GP_ERROR_CORRUPTED_DATA); \
84 #ifndef HAVE_TM_GMTOFF
85 /* required for time conversions in canon_int_set_time() */
86 extern long int timezone;
90 ricoh_send (Camera *camera, GPContext *context, unsigned char cmd,
92 const unsigned char *data, unsigned char len)
95 unsigned int i, w, crc = 0;
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));
109 CR (gp_port_write (camera->port, buf, 4));
110 crc = updcrc (cmd, crc);
111 crc = updcrc (len, crc);
114 * Write data (escape DLE).
116 * w ... bytes written
120 for (i = w; i < len; i++) {
121 crc = updcrc (data[i], crc);
122 if (data[i] == 0x10) {
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));
140 CR (gp_port_write (camera->port, buf, 6));
146 ricoh_send_ack (Camera *camera, GPContext *context)
148 CR (gp_port_write (camera->port, "\x10\x06", 2));
153 ricoh_send_nack (Camera *camera, GPContext *context)
155 CR (gp_port_write (camera->port, "\x10\x15", 2));
160 ricoh_recv (Camera *camera, GPContext *context, unsigned char *cmd,
161 unsigned char *number, unsigned char *data, unsigned char *len)
163 unsigned char buf[6];
164 unsigned char r, i, ii, last_dle;
165 unsigned int crc = 0;
167 for (ii = 0; ; ii++) {
171 * Get header (DLE,STX). If we receive (DLE,ACK), just
172 * drop that and read on.
174 for (i = 0, buf[1] = ACK; i < 4; i++) {
175 CR (gp_port_read (camera->port, buf, 2));
177 gp_context_error (context, _("We expected "
178 "0x%x but received 0x%x. Please "
180 DLE, buf[0], MAIL_GPHOTO_DEVEL);
181 return (GP_ERROR_CORRUPTED_DATA);
191 gp_context_error (context, _("We expected "
192 "0x%x but received 0x%x. Please "
194 STX, buf[1], MAIL_GPHOTO_DEVEL);
195 return GP_ERROR_CORRUPTED_DATA;
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);
204 * Get data (check for DLEs).
205 * r ... number of bytes received
210 CR (gp_port_read (camera->port, data + r, *len - r));
215 for (i = r; i < *len; i++) {
216 if (data[r] == DLE) {
218 data[r + 1] != DLE) {
219 gp_context_error (context,
221 "(0x%x, 0x%x). Please "
223 data[r], data[r + 1], MAIL_GPHOTO_DEVEL);
224 return (GP_ERROR_CORRUPTED_DATA);
226 memmove (&data[r], &data[r +1],
230 crc = updcrc (data[r], crc);
239 CR (gp_port_read (camera->port, buf, 6));
241 if ((buf[0] != DLE) || (buf[1] != ETX && buf[1] != ETB))
242 return (GP_ERROR_CORRUPTED_DATA);
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));
253 /* Acknowledge the packet. */
254 CR (ricoh_send_ack (camera, context));
256 /* If camera is busy, try again (but at most 4 times). */
257 if ((*len == 3) && (data[0] == 0x00) &&
261 gp_context_error (context, _("Camera busy. "
262 "If the problem persists, please "
263 "contact %s."), MAIL_GPHOTO_DEVEL);
269 /* Everything is ok. Break out of loop. */
273 /* Sequence number */
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)
285 unsigned char ret_cmd;
290 CR (ricoh_send (camera, context, cmd, 0, data, len));
291 result = ricoh_recv (camera, context, &ret_cmd, NULL,
294 case GP_ERROR_TIMEOUT:
296 gp_context_error (context, _("Timeout "
297 "even after 2 retries. Please "
298 "contact %s."), MAIL_GPHOTO_DEVEL);
299 return (GP_ERROR_TIMEOUT);
301 GP_DEBUG ("Timeout! Retrying...");
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);
312 gp_context_error (context, _("Communication "
313 "error even after 2 retries. Please "
314 "contact %s."), MAIL_GPHOTO_DEVEL);
320 /* Check if the camera reported success. */
321 if ((*ret_len >= 2) && (ret_data[0] == 0x00) &&
322 (ret_data[1] == 0x00))
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))
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)) {
336 gp_context_error (context, _("Camera busy. "
337 "If the problem persists, please "
338 "contact %s."), MAIL_GPHOTO_DEVEL);
345 * It could be that the camera is in the wrong mode to
346 * execute this command.
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);
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);
365 gp_context_error (context, _("An unknown error occurred. "
366 "Please contact %s."), MAIL_GPHOTO_DEVEL);
370 /* Success! We don't need the first two bytes any more. */
373 memmove (ret_data, ret_data + 2, *ret_len);
379 ricoh_get_pic_size (Camera *camera, GPContext *context, unsigned int n,
382 unsigned char p[3], buf[0xff], len;
384 GP_DEBUG ("Getting size of picture %i...", n);
389 CR (ricoh_transmit (camera, context, 0x95, p, 3, buf, &len));
390 C_LEN (context, len, 4);
393 *size = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0] << 0;
398 #define B2H( bcd ) ((bcd>>4)*10+(bcd&0xF))
401 ricoh_get_pic_date (Camera *camera, GPContext *context, unsigned int n,
404 unsigned char p[3], buf[0xff], len;
407 GP_DEBUG ("Getting date of picture %i...", n);
412 CR (ricoh_transmit (camera, context, 0x95, p, 3, buf, &len));
413 C_LEN (context, len, 7);
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]);
425 *date = mktime (&time);
432 ricoh_get_pic_name (Camera *camera, GPContext *context, unsigned int n,
435 unsigned char p[3], len;
436 static unsigned char buf[0xff];
438 GP_DEBUG ("Getting name of picture %i...", n);
443 CR (ricoh_transmit (camera, context, 0x95, p, 3, buf, &len));
454 ricoh_get_pic_memo (Camera *camera, GPContext *context, unsigned int n,
457 unsigned char p[3], len;
458 static unsigned char buf[0xff];
460 GP_DEBUG ("Getting memo of picture %i...", n);
465 CR (ricoh_transmit (camera, context, 0x95, p, 3, buf, &len));
476 ricoh_del_pic (Camera *camera, GPContext *context, unsigned int n)
478 unsigned char p[2], buf[0xff], len;
480 GP_DEBUG ("Deleting picture %i...", n);
482 /* Put camera in delete mode */
483 CR (ricoh_transmit (camera, context, 0x97, NULL, 0, buf, &len));
484 C_LEN (context, len, 0);
486 /* Find and send picture to delete */
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);
498 ricoh_get_num (Camera *camera, GPContext *context, unsigned int *n)
500 unsigned char p[2], buf[0xff], len;
502 GP_DEBUG ("Getting number of pictures...");
506 CR (ricoh_transmit (camera, context, 0x51, p, 2, buf, &len));
507 C_LEN (context, len, 2);
510 *n = (buf[1] << 8) | buf[0];
516 ricoh_set_speed (Camera *camera, GPContext *context, RicohSpeed speed)
518 unsigned char p[1], buf[0xff], len;
521 CR (ricoh_transmit (camera, context, 0x32, p, 1, buf, &len));
522 C_LEN (context, len, 0);
524 /* Wait for camera to switch speed. */
531 ricoh_connect (Camera *camera, GPContext *context, RicohModel *model)
533 unsigned char p[3], buf[0xff], len;
538 CR (ricoh_transmit (camera, context, 0x31, p, 3, buf, &len));
539 C_LEN (context, len, 4);
543 *model = (buf[0] << 8) | buf[1];
545 /* No idea what buf[2] and buf[3] contain. */
551 ricoh_disconnect (Camera *camera, GPContext *context)
553 unsigned char buf[0xff], len;
555 CR (ricoh_transmit (camera, context, 0x37, NULL, 0, buf, &len));
556 C_LEN (context, len, 2);
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
582 ricoh_get_pic (Camera *camera, GPContext *context, unsigned int n,
583 RicohFileType type, unsigned char **data, unsigned int *size)
585 unsigned char p[2], cmd, buf[0xff], len;
586 unsigned int r, header_len;
589 GP_DEBUG ("Getting image %i as %s...", n,
590 (type==RICOH_FILE_TYPE_PREVIEW ? "thumbnail":"image"));
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));
597 /* Send picture number */
600 CR (ricoh_transmit (camera, context, (unsigned char) type,
602 C_LEN (context, len, 16);
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.
609 header_len = (type == RICOH_FILE_TYPE_PREVIEW) ? sizeof (header) : 0;
610 *size = buf[15] << 24 | buf[14] << 16 | buf[13] << 8 | buf[12];
613 *data = malloc (*size);
615 return (GP_ERROR_NO_MEMORY);
619 * r ... number of bytes received
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);
627 /* In case of previews, copy over the TIFF header. */
628 if (type == RICOH_FILE_TYPE_PREVIEW)
629 memcpy (*data, header, header_len);
635 ricoh_get_date (Camera *camera, GPContext *context, time_t *date)
637 unsigned char p[1], buf[0xff], len;
641 CR (ricoh_transmit (camera, context, 0x51, p, 1, buf, &len));
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);
654 *date = mktime (&time);
662 #define HEX(x) (((x)/10)<<4)+((x)%10)
665 ricoh_set_date (Camera *camera, GPContext *context, time_t time)
667 unsigned char p[8], buf[0xff], len;
672 /* Call localtime() to get 'extern long timezone' */
673 t = localtime (&time);
674 #ifdef HAVE_TM_GMTOFF
675 time += t->tm_gmtoff;
679 t = localtime (&time);
680 GP_DEBUG ("ricoh_set_date: converted time to localtime %s "
681 "(timezone is %ld)", asctime (t), timezone);
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));
695 /* get the cameras memory size */
697 ricoh_get_cam_mem (Camera *camera, GPContext *context, int *size)
699 unsigned char p[2], buf[0xff], len;
703 CR (ricoh_transmit (camera, context, 0x51, p, 2, buf, &len));
704 C_LEN (context, len, 4);
707 *size = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
712 /* get the cameras available memory size */
714 ricoh_get_cam_amem (Camera *camera, GPContext *context, int *size)
716 unsigned char p[2], buf[0xff], len;
720 CR (ricoh_transmit (camera, context, 0x51, p, 2, buf, &len));
721 C_LEN (context, len, 4);
724 *size = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
729 #define RICOH_GET_SET_VALUE(name,type,code) \
731 ricoh_get_##name (Camera *camera, GPContext *context, \
734 unsigned char p[1], buf[0xff], len; \
737 CR (ricoh_transmit (camera, context, 0x51, p, 1, buf, &len)); \
738 C_LEN (context, len, 1); \
745 ricoh_set_##name (Camera *camera, GPContext *context, \
748 unsigned char p[2], buf[0xff], len; \
751 p[1] = (unsigned char) value; \
752 CR (ricoh_transmit (camera, context, 0x50, p, 2, buf, &len)); \
753 C_LEN (context, len, 0); \
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)
769 ricoh_get_copyright (Camera *camera, GPContext *context, const char **copyright)
771 unsigned char p[1], len;
772 static char buf[1024];
775 CR (ricoh_transmit (camera, context, 0x51, p, 1, buf, &len));
777 if (copyright && *copyright) {
786 ricoh_set_copyright (Camera *camera, GPContext *context, const char *copyright)
788 unsigned char p[21], len, buf[0xff];
791 strncpy (p + 1, copyright, 20);
792 CR (ricoh_transmit (camera, context, 0x50, p, 21, buf, &len));
798 ricoh_take_pic (Camera *camera, GPContext *context)
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));
809 CR (ricoh_send (camera, context, 0x60, 0x00, p, 1));
815 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
818 ricoh_put_file (Camera *camera, GPContext *context, const char *name,
819 const unsigned char *data, unsigned int size)
822 unsigned char p[16], len, buf[0xff], block[0xff];
823 unsigned int pic_num, i, pr;
825 CR (ricoh_get_mode (camera, context, &mode));
826 if (mode != RICOH_MODE_PLAY)
827 CR (ricoh_set_mode (camera, context, RICOH_MODE_PLAY));
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));
837 strncpy (p, name, 12);
842 CR (ricoh_transmit (camera, context, 0xa1, p, 16, buf, &len));
843 C_LEN (context, len, 2);
846 * We just received the picture number of the new file. We don't
849 pic_num = buf[0] | (buf[1] << 8);
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,
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));
863 gp_context_progress_stop (context, pr);
868 CR (ricoh_transmit (camera, context, 0x50, p, 2, buf, &len));
869 C_LEN (context, len, 0);