Logo Search packages:      
Sourcecode: libgphoto2 version File versions

samsung.c

/* samsung.c
 *
 * Copyright © 2000 James McKenzie
 * Copyright © 2001 Lutz Müller
 * Copyright © 2002 Marcus Meissner
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#include "config.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <gphoto2-library.h>

/* The commands */
#define SDSC_START      0x43
#define SDSC_NEXT     0x53
#define SDSC_BINARY     0x06
#define SDSC_RETRANSMIT 0x15

#define SDSC_BLOCKSIZE 0x400
#define SDSC_INFOSIZE  0x080

#define SDSC_TIMEOUT    500
#define SDSC_RETRIES      3

/* Our own error codes */
#define SDSC_ERROR_EOF -1001

#define CHECK_RESULT(result) {int r = result; if (r < 0) return (r);}

#ifdef ENABLE_NLS
#  include <libintl.h>
#  undef _
#  define _(String) dgettext (GETTEXT_PACKAGE, String)
#  ifdef gettext_noop
#    define N_(String) gettext_noop (String)
#  else
#    define N_(String) (String)
#  endif
#else
#  define _(String) (String)
#  define N_(String) (String)
#endif

static int
SDSC_send (GPPort *port, unsigned char command)
{
      CHECK_RESULT (gp_port_write (port, &command, 1));

      return (GP_OK);
}

static int
SDSC_receive (GPPort *port, unsigned char *buf, int length)
{
      char tmp[3];
      int i, result = GP_OK;

      for (i = 0; i < SDSC_RETRIES; i++) {

            /* Read the header (3 bytes) and check for EOF */
            CHECK_RESULT (gp_port_read (port, tmp, 1));
            if (tmp[0] == 0x04)
                  return (SDSC_ERROR_EOF);
            result = gp_port_read (port, tmp, 2);
            if (result < 0) {
                  CHECK_RESULT (SDSC_send (port, SDSC_RETRANSMIT));
                  continue;
            }

            /* Read data */
            result = gp_port_read (port, buf, length);
            if (result < 0) {
                  CHECK_RESULT (SDSC_send (port, SDSC_RETRANSMIT));
                  continue;
            }

            /* Read footer (2 bytes) */
            result = gp_port_read (port, tmp, 2);
            if (result < 0) {
                  CHECK_RESULT (SDSC_send (port, SDSC_RETRANSMIT));
                  continue;
            }
            break;
      }

      return (result);
}

static int
is_null (unsigned char *buf)
{
      int n = 128;
      
      while (n--)
            if (*(buf++))
                  return (0);
      return (1);
}

static int
SDSC_initialize (GPPort *port)
{
      unsigned char buffer[SDSC_INFOSIZE];

      /* Read out a header */
      do {
            CHECK_RESULT (SDSC_send (port, SDSC_NEXT));
            CHECK_RESULT (SDSC_send (port, SDSC_START));
            CHECK_RESULT (SDSC_receive (port, buffer, SDSC_INFOSIZE));
      } while (!is_null (buffer));
      return (GP_OK);
}

int
camera_id (CameraText *id) 
{
      strcpy (id->text, "samsung");

      return (GP_OK);
}

static struct {
      const char *model;
} models[] = {
      {"Samsung:digimax 800k"},
      {"Dynatron:Dynacam 800"},
      {"Jenoptik:JD12 800ff"},
      {"Praktica:QD800"},
      {NULL}
};

int
camera_abilities (CameraAbilitiesList *list) 
{
      int i;
      CameraAbilities a;

      for (i = 0; models[i].model; i++) {
            memset (&a, 0, sizeof(a));
            strcpy (a.model, models[i].model);
            a.status          = GP_DRIVER_STATUS_PRODUCTION;
            a.port            = GP_PORT_SERIAL;
            a.speed[0]        = 115200;
            a.speed[1]        = 0;
            a.operations            = GP_OPERATION_NONE;
            a.file_operations = GP_FILE_OPERATION_NONE;
            a.folder_operations     = GP_FOLDER_OPERATION_NONE;
            CHECK_RESULT (gp_abilities_list_append (list, a));
      }
      return (GP_OK);
}

static int
get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
             CameraFileType type, CameraFile *file, void *user_data,
             GPContext *context)
{
      Camera *camera = user_data;
      int result;
      int havefirst = 0;
      unsigned char buffer[SDSC_BLOCKSIZE], first[SDSC_BLOCKSIZE];
      long int size, curread;
      unsigned int pid;

      if (type != GP_FILE_TYPE_NORMAL)
            return (GP_ERROR_NOT_SUPPORTED);

      /* Seek the header of our file */
      while (1) {
            CHECK_RESULT (SDSC_send (camera->port, SDSC_NEXT));
            CHECK_RESULT (SDSC_send (camera->port, SDSC_START));
            CHECK_RESULT (SDSC_receive (camera->port, buffer, SDSC_INFOSIZE));
            if (!strcmp(buffer,filename))
                break;
            if (is_null(buffer)) { /* skipped to the end of the camera? */
                /* Since we start at a random position, we wrap around. */
                continue;
              }
            /* We are at the first item again, so break. */
            if (havefirst && !strcmp(first,buffer))
                  return GP_ERROR_BAD_PARAMETERS;
            if (!havefirst) {
                  havefirst = 1;
                  strcpy(first,buffer);
            }
      }
      /* The buffer header has
       * filename (8.3 DOS format and \0)
       * filesize (as ascii number) and \0
       */
      /* Extract the size of the file */
      sscanf(buffer+12,"%ld",&size);
      /* Put the camera into image mode */
      CHECK_RESULT (SDSC_send (camera->port, SDSC_BINARY));
      CHECK_RESULT (SDSC_send (camera->port, SDSC_START));

      pid = gp_context_progress_start(context,size,_("Downloading image..."));

      curread = 0;
      /* Read data */
      while (1) {
            /* Read data and check for EOF */
            result = SDSC_receive (camera->port, buffer, SDSC_BLOCKSIZE);
            if (result == SDSC_ERROR_EOF)
                  break;
            if (result < 0)
                  return result;
            gp_file_append(file,buffer,SDSC_BLOCKSIZE);
            curread += SDSC_BLOCKSIZE;
              gp_context_progress_update(context, pid, curread);
            if (gp_context_cancel(context) == GP_CONTEXT_FEEDBACK_CANCEL)
                return GP_ERROR_CANCEL;
            CHECK_RESULT (SDSC_send (camera->port, SDSC_BINARY));
      }
      gp_context_progress_stop(context, pid);
      CHECK_RESULT (gp_file_set_mime_type (file, GP_MIME_JPEG));
      return (GP_OK);
}

static int
camera_about (Camera *camera, CameraText *about, GPContext *context) 
{
      /* Translators: please write 'M"uller' and 'Mei"sner' (that
         is, with u-umlaut and eszett resp.) if your charset
         allows it.  If not, use "Mueller" and "Meissner".  */
      strcpy (about->text, _("The Samsung digimax 800k driver has "
            "been written by James McKenzie "
            "<james@fishsoup.dhs.org> for gphoto. "
            "Lutz Mueller <lutz@users.sourceforge.net> ported it to "
            "gphoto2. Marcus Meissner <marcus@jet.franken.de> fixed "
            "and enhanced the port.")
            );

      return (GP_OK);
}

static int
file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
            void *data, GPContext *context)
{
      unsigned char buffer[SDSC_INFOSIZE];
      Camera *camera = data;

      /* Rewind */
      CHECK_RESULT (SDSC_initialize (camera->port)); 

      /* Count the pictures */
      while (1) {
            CHECK_RESULT (SDSC_send (camera->port, SDSC_NEXT));
            CHECK_RESULT (SDSC_send (camera->port, SDSC_START));
            CHECK_RESULT (SDSC_receive (camera->port,
                        buffer, SDSC_INFOSIZE));
            if (is_null (buffer))
                  break;
            gp_list_append(list, buffer, NULL);
      }
      return (GP_OK);
}

static int
get_info_func (CameraFilesystem *fs, const char *folder, const char *filename,
               CameraFileInfo *info, void *data, GPContext *context)
{
      Camera *camera = data;
      int havefirst = 0;
      unsigned char buffer[SDSC_INFOSIZE], first[SDSC_INFOSIZE];

      info->file.fields = GP_FILE_INFO_NONE;
      /* Don't rewind, just go forward until we find it.
       * Works way better for linear queries. 
       */
      while (1) {
            CHECK_RESULT (SDSC_send (camera->port, SDSC_NEXT));
            CHECK_RESULT (SDSC_send (camera->port, SDSC_START));
            CHECK_RESULT (SDSC_receive (camera->port,buffer,SDSC_INFOSIZE));
            if (is_null (buffer))
                  continue;
            if (!strcmp(buffer,filename)) {
                  info->file.fields = GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT | GP_FILE_INFO_SIZE | GP_FILE_INFO_NAME;
                  info->file.width  = 1024;
                  info->file.height = 768;
                  strcpy(info->file.type,GP_MIME_JPEG);
                  strcpy(info->file.name,buffer);
                  sscanf(buffer+12,"%ld",&info->file.size);
                  return GP_OK;
              }
            /* We are at the first item again */
            if (havefirst && !strcmp(first,buffer))
                  break;
            if (!havefirst) {
                  havefirst = 1;
                  strcpy(first,buffer);
            }
      }
      return (GP_OK);
}


int
camera_init (Camera *camera, GPContext *context) 
{
      GPPortSettings settings;

        /* First, set up all the function pointers */
        camera->functions->about                = camera_about;

      /* Now, tell the filesystem where to get lists and info */
      gp_filesystem_set_list_funcs (camera->fs, file_list_func, NULL, camera);
      gp_filesystem_set_file_funcs (camera->fs, get_file_func, NULL, camera);
      gp_filesystem_set_info_funcs (camera->fs, get_info_func, NULL, camera);

      /* Some settings */
      CHECK_RESULT (gp_port_get_settings (camera->port, &settings));
      settings.serial.speed   = 115200;
      settings.serial.bits    = 8;
      settings.serial.parity  = 0;
      settings.serial.stopbits= 1;
      CHECK_RESULT (gp_port_set_settings (camera->port, settings));
      CHECK_RESULT (gp_port_set_timeout (camera->port, SDSC_TIMEOUT));
      /* Open the port and check if the camera is there */
      CHECK_RESULT (SDSC_initialize (camera->port));
      return (GP_OK);
}

Generated by  Doxygen 1.6.0   Back to index