2 Copyright © 2000 Mariusz Zynel <mariusz@mizar.org> (gPhoto port)
3 Copyright © 2000 Fredrik Roubert <roubert@df.lth.se> (idea)
4 Copyright © 1999 Galen Brooks <galen@nine.com> (DC1580 code)
6 This file is part of the gPhoto project and may only be used, modified,
7 and distributed under the terms of the gPhoto project license, COPYING.
8 By continuing to use, modify, or distribute this file you indicate that
9 you have read the license, understand and accept it fully.
11 THIS SOFTWARE IS PROVIDED AS IS AND COME WITH NO WARRANTY OF ANY KIND,
12 EITHER EXPRESSED OR IMPLIED. IN NO EVENT WILL THE COPYRIGHT HOLDER BE
13 LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE.
17 This is a Panasonic PV/NV-DC1580 camera gPhoto library source code.
19 An algorithm for checksums borrowed from Michael McCormack's Nikon
20 CoolPix 600 library for gPhoto1.
38 # define _(String) dgettext (GETTEXT_PACKAGE, String)
40 # define N_(String) gettext_noop (String)
42 # define N_(String) (String)
45 # define _(String) (String)
46 # define N_(String) (String)
53 # define __FILE__ "dc1580.c"
56 #define GP_MODULE "dc1580"
58 /******************************************************************************/
60 /* Internal utility functions */
62 /* dsc2_checksum - establish checksum for size bytes in buffer */
64 static uint8_t dsc2_checksum(char *buffer, int size) {
69 for (i = 1; i < size - 2; i++) {
70 checksum += buffer[i];
77 /* dsc2_sendcmd - send command with data to DSC */
79 static int dsc2_sendcmd(Camera *camera, uint8_t cmd, long int data, uint8_t sequence) {
83 DEBUG_PRINT_MEDIUM(("Sending command: 0x%02x, data: %i, sequence: %i.", cmd, data, sequence));
85 memset(camera->pl->buf, 0, 16);
87 camera->pl->buf[0] = 0x08;
88 camera->pl->buf[1] = sequence;
89 camera->pl->buf[2] = 0xff - sequence;
90 camera->pl->buf[3] = cmd;
92 for (i = 0; i < sizeof(data); i++)
93 camera->pl->buf[4 + i] = (uint8_t)(data >> 8*i);
95 camera->pl->buf[14] = dsc2_checksum(camera->pl->buf, 16);
97 return gp_port_write(camera->port, camera->pl->buf, 16);
100 /* dsc2_retrcmd - retrieve command and its data from DSC */
102 static int dsc2_retrcmd(Camera *camera) {
104 int result = GP_ERROR;
107 if ((s = gp_port_read(camera->port, camera->pl->buf, 16)) == GP_ERROR)
110 /* Make sense in debug only. Done on gp_port level.
112 dsc_dumpmem(camera->pl->buf, s);
115 if (s != 16 || camera->pl->buf[DSC2_BUF_BASE] != 0x08 ||
116 camera->pl->buf[DSC2_BUF_SEQ] != 0xff - (uint8_t)camera->pl->buf[DSC2_BUF_SEQC]) {
117 RETURN_ERROR(EDSCBADRSP);
121 result = camera->pl->buf[DSC2_BUF_CMD];
123 DEBUG_PRINT_MEDIUM(("Retrieved command: %i.", result));
128 /* dsc2_connect - try hand shake with camera and establish connection */
130 static int dsc2_connect(Camera *camera, int speed) {
132 DEBUG_PRINT_MEDIUM(("Connecting camera with speed: %i.", speed));
134 if (dsc1_setbaudrate(camera, speed) != GP_OK)
137 if (dsc1_getmodel(camera) != DSC2)
138 RETURN_ERROR(EDSCBADDSC);
139 /* bad camera model */
141 if (dsc2_sendcmd(camera, DSC2_CMD_CONNECT, 0, 0) != GP_OK)
144 if (dsc2_retrcmd(camera) != DSC2_RSP_OK)
145 RETURN_ERROR(EDSCBADRSP);
148 DEBUG_PRINT_MEDIUM(("Camera connected successfully."));
153 /* dsc2_disconnect - reset camera, free buffers and close files */
155 static int dsc2_disconnect(Camera *camera) {
157 DEBUG_PRINT_MEDIUM(("Disconnecting the camera."));
159 if (dsc2_sendcmd(camera, DSC2_CMD_RESET, 0, 0) != GP_OK)
162 if (dsc2_retrcmd(camera) != DSC2_RSP_OK)
163 RETURN_ERROR(EDSCBADRSP)
166 sleep(DSC_PAUSE); /* let camera to redraw its screen */
168 DEBUG_PRINT_MEDIUM(("Camera disconnected."));
173 /* dsc2_getindex - retrieve the number of images stored in camera memory */
175 static int dsc2_getindex(Camera *camera) {
177 int result = GP_ERROR;
179 DEBUG_PRINT_MEDIUM(("Retrieving the number of images."));
181 if (dsc2_sendcmd(camera, DSC2_CMD_GET_INDEX, 0, 0) != GP_OK)
184 if (dsc2_retrcmd(camera) == DSC2_RSP_INDEX)
186 ((uint32_t)camera->pl->buf[DSC2_BUF_DATA]) |
187 ((uint8_t)camera->pl->buf[DSC2_BUF_DATA + 1] << 8) |
188 ((uint8_t)camera->pl->buf[DSC2_BUF_DATA + 2] << 16) |
189 ((uint8_t)camera->pl->buf[DSC2_BUF_DATA + 3] << 24);
191 RETURN_ERROR(EDSCBADRSP);
194 DEBUG_PRINT_MEDIUM(("Number of images: %i", result));
199 /* dsc2_delete - delete image #index from camera memory */
201 static int dsc2_delete(Camera *camera, int index) {
203 DEBUG_PRINT_MEDIUM(("Deleting image: %i.", index));
206 RETURN_ERROR(EDSCBADNUM);
207 /* bad image number */
209 if (dsc2_sendcmd(camera, DSC2_CMD_DELETE, index, 0) != GP_OK)
212 if (dsc2_retrcmd(camera) != DSC2_RSP_OK)
213 RETURN_ERROR(EDSCBADRSP);
216 DEBUG_PRINT_MEDIUM(("Image: %i deleted.", index));
220 /* dsc2_selectimage - select image to download, return its size */
222 static int dsc2_selectimage(Camera *camera, int index, int thumbnail) {
226 DEBUG_PRINT_MEDIUM(("Selecting image: %i, thumbnail: %i.", index, thumbnail));
229 RETURN_ERROR(EDSCBADNUM);
230 /* bad image number */
232 if (thumbnail == DSC_THUMBNAIL) {
233 if (dsc2_sendcmd(camera, DSC2_CMD_THUMB, index, 0) != GP_OK)
236 if (dsc2_sendcmd(camera, DSC2_CMD_SELECT, index, 0) != GP_OK)
240 if (dsc2_retrcmd(camera) != DSC2_RSP_IMGSIZE)
241 RETURN_ERROR(EDSCBADRSP);
244 size = ((uint32_t)camera->pl->buf[DSC2_BUF_DATA]) |
245 ((uint8_t)camera->pl->buf[DSC2_BUF_DATA + 1] << 8) |
246 ((uint8_t)camera->pl->buf[DSC2_BUF_DATA + 2] << 16) |
247 ((uint8_t)camera->pl->buf[DSC2_BUF_DATA + 3] << 24);
249 DEBUG_PRINT_MEDIUM(("Selected image: %i, thumbnail: %i, size: %i.", index, thumbnail, size));
254 /* gp_port_readimageblock - read #block block (1024 bytes) of an image into buf */
256 static int dsc2_readimageblock(Camera *camera, int block, char *buffer) {
258 DEBUG_PRINT_MEDIUM(("Reading image block: %i.", block));
260 if (dsc2_sendcmd(camera, DSC2_CMD_GET_DATA, block, block) != GP_OK)
263 if (gp_port_read(camera->port, camera->pl->buf, DSC_BUFSIZE) != DSC_BUFSIZE)
264 RETURN_ERROR(EDSCBADRSP);
267 if ((uint8_t)camera->pl->buf[0] != 1 ||
268 (uint8_t)camera->pl->buf[1] != block ||
269 (uint8_t)camera->pl->buf[2] != 0xff - block ||
270 (uint8_t)camera->pl->buf[3] != DSC2_RSP_DATA ||
271 (uint8_t)camera->pl->buf[DSC_BUFSIZE - 2] != dsc2_checksum(camera->pl->buf, DSC_BUFSIZE))
272 RETURN_ERROR(EDSCBADRSP);
276 memcpy(buffer, &camera->pl->buf[4], DSC_BLOCKSIZE);
278 DEBUG_PRINT_MEDIUM(("Block: %i read in.", block));
280 return DSC_BLOCKSIZE;
283 /* dsc2_readimage - read #index image or thumbnail and return its contents */
286 static char *dsc2_readimage(Camera *camera, int index, int thumbnail, int *size) {
292 DEBUG_PRINT_MEDIUM(("Reading image: %i, thumbnail: %i.", index, thumbnail));
294 if ((*size = dsc2_selectimage(camera, index, thumbnail)) < 0)
297 if (thumbnail == DSC_THUMBNAIL)
298 strcpy(kind, "thumbnail");
300 strcpy(kind, "image");
302 if (!(buffer = (char*)malloc(*size))) {
303 DEBUG_PRINT_MEDIUM(("Failed to allocate memory for %s data.", kind));
307 blocks = (*size - 1)/DSC_BLOCKSIZE + 1;
309 for (i = 0; i < blocks; i++) {
310 if (dsc2_readimageblock(camera, i, &buffer[i*DSC_BLOCKSIZE]) == GP_ERROR) {
311 DEBUG_PRINT_MEDIUM(("Error during %s transfer.", kind));
317 DEBUG_PRINT_MEDIUM(("Image: %i read in.", index));
323 /* dsc2_setimagesize - set size of an image to upload to camera */
325 static int dsc2_setimagesize(Camera *camera, int size) {
327 DEBUG_PRINT_MEDIUM(("Setting image size to: %i.", size));
329 if (dsc2_sendcmd(camera, DSC2_CMD_SET_SIZE, size, 0) != GP_OK)
332 if (dsc2_retrcmd(camera) != DSC2_RSP_OK)
333 RETURN_ERROR(EDSCBADRSP);
336 DEBUG_PRINT_MEDIUM(("Image size set to: %i.", size));
341 /* gp_port_writeimageblock - write size bytes from buffer rounded to 1024 bytes to camera */
343 static int dsc2_writeimageblock(Camera *camera, int block, char *buffer, int size) {
345 DEBUG_PRINT_MEDIUM(("Writing image block: %i.", block));
347 memset(camera->pl->buf, 0, DSC_BUFSIZE);
349 camera->pl->buf[0] = 0x01;
350 camera->pl->buf[1] = block;
351 camera->pl->buf[2] = 0xff - block;
352 camera->pl->buf[3] = DSC2_CMD_SEND_DATA;
354 if (DSC_BLOCKSIZE < size)
355 size = DSC_BLOCKSIZE;
357 memcpy(&camera->pl->buf[4], buffer, size);
359 camera->pl->buf[DSC_BUFSIZE - 2] = dsc2_checksum(camera->pl->buf, DSC_BUFSIZE);
361 if (gp_port_write(camera->port, camera->pl->buf, DSC_BUFSIZE) != GP_OK)
364 if (dsc2_retrcmd(camera) != DSC2_RSP_OK)
365 RETURN_ERROR(EDSCBADRSP);
368 DEBUG_PRINT_MEDIUM(("Block: %i of size: %i written.", block, size));
373 /* dsc2_writeimage - write an image to camera memory, size bytes at buffer */
376 static int dsc2_writeimage(Camera *camera, char *buffer, int size) {
378 int blocks, blocksize, i;
380 DEBUG_PRINT_MEDIUM(("Writing an image of size: %i.", size));
382 if ((dsc2_setimagesize(camera, size)) != GP_OK)
385 blocks = (size - 1)/DSC_BLOCKSIZE + 1;
387 for (i = 0; i < blocks; i++) {
388 blocksize = size - i*DSC_BLOCKSIZE;
389 if (DSC_BLOCKSIZE < blocksize)
390 blocksize = DSC_BLOCKSIZE;
391 if (dsc2_writeimageblock(camera, i, &buffer[i*DSC_BLOCKSIZE], blocksize) != GP_OK) {
392 DEBUG_PRINT_MEDIUM(("Error during image transfer."));
397 DEBUG_PRINT_MEDIUM(("Image written successfully."));
403 /* dsc2_preview - show selected image on camera's LCD */
406 static int dsc2_preview(Camera *camera, int index) {
409 RETURN_ERROR(EDSCBADNUM);
410 /* bad image number */
412 if (dsc2_sendcmd(camera, DSC2_CMD_PREVIEW, index, 0) != GP_OK)
415 if (dsc2_retrcmd(camera) != DSC2_RSP_OK)
416 RETURN_ERROR(EDSCBADRSP);
423 /******************************************************************************/
425 /* Library interface functions */
427 int camera_id (CameraText *id) {
429 strcpy(id->text, "panasonic-dc1580");
434 int camera_abilities (CameraAbilitiesList *list) {
444 memset(&a, 0, sizeof(a));
445 a.status = GP_DRIVER_STATUS_PRODUCTION;
446 strcpy(a.model, models[i]);
447 a.port = GP_PORT_SERIAL;
454 a.operations = GP_OPERATION_NONE;
455 a.file_operations = GP_FILE_OPERATION_DELETE |
456 GP_FILE_OPERATION_PREVIEW;
457 a.folder_operations = GP_FOLDER_OPERATION_PUT_FILE;
459 CHECK (gp_abilities_list_append(list, a));
466 static int camera_exit (Camera *camera, GPContext *context) {
467 gp_context_status(context, _("Disconnecting camera."));
468 dsc2_disconnect(camera);
469 if (camera->pl->buf) {
470 free (camera->pl->buf);
471 camera->pl->buf = NULL;
478 static int file_list_func (CameraFilesystem *fs, const char *folder,
479 CameraList *list, void *data, GPContext *context) {
481 Camera *camera = data;
484 CHECK (count = dsc2_getindex(camera));
486 CHECK (gp_list_populate(list, DSC_FILENAMEFMT, count));
491 static int get_info_func (CameraFilesystem *fs, const char *folder,
492 const char *filename, CameraFileInfo *info,
493 void *data, GPContext *context) {
495 Camera *camera = data;
498 /* index is the 0-based image number on the camera */
499 CHECK (index = gp_filesystem_number(camera->fs, folder, filename, context));
502 info->file.fields = GP_FILE_INFO_TYPE | GP_FILE_INFO_NAME | GP_FILE_INFO_SIZE;
503 strcpy(info->file.type, GP_MIME_JPEG);
504 sprintf(info->file.name, DSC_FILENAMEFMT, index);
505 info->file.size = dsc2_selectimage(camera, index, DSC_FULLIMAGE);
507 info->preview.fields = GP_FILE_INFO_TYPE | GP_FILE_INFO_NAME | GP_FILE_INFO_SIZE;
508 strcpy(info->preview.type, GP_MIME_JPEG);
509 info->preview.size = dsc2_selectimage(camera, index, DSC_THUMBNAIL);
514 static int get_file_func (CameraFilesystem *fs, const char *folder,
515 const char *filename, CameraFileType type,
516 CameraFile *file, void *data, GPContext *context) {
518 Camera *camera = data;
519 int index, i, size, blocks, result;
522 gp_context_status(context, _("Downloading %s."), filename);
524 /* index is the 0-based image number on the camera */
525 CHECK (index = gp_filesystem_number(camera->fs, folder, filename, context));
529 case GP_FILE_TYPE_PREVIEW:
530 size = dsc2_selectimage(camera, index, DSC_THUMBNAIL);
532 case GP_FILE_TYPE_NORMAL:
533 size = dsc2_selectimage(camera, index, DSC_FULLIMAGE);
536 return (GP_ERROR_NOT_SUPPORTED);
541 CHECK (gp_file_set_name(file, filename));
542 CHECK (gp_file_set_mime_type(file, GP_MIME_JPEG));
544 blocks = (size - 1)/DSC_BLOCKSIZE + 1;
546 id = gp_context_progress_start (context, blocks, _("Getting data..."));
547 for (i = 0; i < blocks; i++) {
548 CHECK (dsc2_readimageblock(camera, i, NULL));
549 CHECK (gp_file_append(file, &camera->pl->buf[4], DSC_BLOCKSIZE));
550 gp_context_progress_update (context, id, i + 1);
551 if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL)
552 return (GP_ERROR_CANCEL);
554 gp_context_progress_stop (context, id);
559 static int put_file_func (CameraFilesystem *fs, const char *folder,
560 CameraFile *file, void *user_data,
561 GPContext *context) {
563 Camera *camera = user_data;
564 int blocks, blocksize, i, result;
570 gp_file_get_name(file, &name);
571 gp_context_status(context, _("Uploading image: %s."), name);
573 /* We can not figure out file type, at least by now.
575 if (strcmp(file->type, "image/jpg") != 0) {
576 dsc_print_message(camera, "JPEG image format allowed only.");
580 gp_file_get_data_and_size (file, &data, &size);
581 if (size > DSC_MAXIMAGESIZE) {
582 gp_context_message (context, _("File size is %ld bytes. "
583 "The size of the largest file possible to "
584 "upload is: %i bytes."), size,
589 if ((result = dsc2_setimagesize(camera, size)) != GP_OK) return result;
591 blocks = (size - 1)/DSC_BLOCKSIZE + 1;
593 id = gp_context_progress_start (context, blocks, _("Uploading..."));
594 for (i = 0; i < blocks; i++) {
595 blocksize = size - i*DSC_BLOCKSIZE;
596 if (DSC_BLOCKSIZE < blocksize)
597 blocksize = DSC_BLOCKSIZE;
598 result = dsc2_writeimageblock(camera, i,
599 (char*)&data[i*DSC_BLOCKSIZE],
603 gp_context_progress_update (context, id, i + 1);
604 if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL)
605 return (GP_ERROR_CANCEL);
607 gp_context_progress_stop (context, id);
612 static int delete_file_func (CameraFilesystem *fs, const char *folder,
613 const char *filename, void *data,
614 GPContext *context) {
616 Camera *camera = data;
619 gp_context_status(context, _("Deleting image %s."), filename);
621 /* index is the 0-based image number on the camera */
622 CHECK (index = gp_filesystem_number (camera->fs, folder, filename, context));
625 return dsc2_delete(camera, index);
628 static int camera_about (Camera *camera, CameraText *about, GPContext *context)
631 _("Panasonic DC1580 gPhoto2 library\n"
632 "Mariusz Zynel <mariusz@mizar.org>\n\n"
633 "Based on dc1000 program written by\n"
634 "Fredrik Roubert <roubert@df.lth.se> and\n"
635 "Galen Brooks <galen@nine.com>."));
639 static CameraFilesystemFuncs fsfuncs = {
640 .file_list_func = file_list_func,
641 .get_info_func = get_info_func,
642 .get_file_func = get_file_func,
643 .put_file_func = put_file_func,
644 .del_file_func = delete_file_func,
647 int camera_init (Camera *camera, GPContext *context)
649 GPPortSettings settings;
650 int result, selected_speed;
652 /* First, set up all the function pointers */
653 camera->functions->exit = camera_exit;
654 camera->functions->about = camera_about;
656 camera->pl = malloc (sizeof (CameraPrivateLibrary));
658 return (GP_ERROR_NO_MEMORY);
659 camera->pl->buf = malloc (sizeof (char) * DSC_BUFSIZE);
660 if (!camera->pl->buf) {
663 return (GP_ERROR_NO_MEMORY);
666 CHECK (gp_port_set_timeout (camera->port, 5000));
668 /* Configure the port (and remember the speed) */
669 CHECK (gp_port_get_settings (camera->port, &settings));
670 selected_speed = settings.serial.speed;
671 settings.serial.speed = 9600; /* hand shake speed */
672 settings.serial.bits = 8;
673 settings.serial.parity = 0;
674 settings.serial.stopbits = 1;
675 CHECK (gp_port_set_settings (camera->port, settings));
677 CHECK (gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera));
678 /* Connect with the selected speed */
679 return dsc2_connect(camera, selected_speed);
682 /* End of dc1580.c */