Logo Search packages:      
Sourcecode: libgphoto2 version File versions

enigma13.c

/* blink2.c
 *
 * Copyright  2004 Olivier Fauchon <olivier@aixmarseille.com>
 *
 * 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <gphoto2/gphoto2-library.h>
#include <gphoto2/gphoto2-port-log.h>
#include <gphoto2/gphoto2-result.h>
#include "gphoto2-endian.h"

#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

#define ENIGMA13_BLK_FLASH_ALIGN 0x2000
#define ENIGMA13_BLK_CARD_ALIGN 0x4000
#define ENIGMA13_USB_TIMEOUT_MS 5000
#define ENIGMA13_WAIT_FOR_READY_TIMEOUT_S 5
#define ENIGMA13_WAIT_TOC_DELAY_MS 500000
#define ENIGMA13_WAIT_IMAGE_READY_MS 300000
#define GP_MODULE "enigma13"


#define CHECK(result) {int res; res = result; if (res < 0) return (res);}


/* the table of content of the camera
   it's filled in enigma_get_toc, and used in enigma_download_img */    
static char* enigma13_static_toc=NULL;




static int enigma13_about (Camera *camera, CameraText *about, GPContext *context)
{
        strcpy (about->text, _("Download program for Digital Dream Enigma 1.3. "
                "by <olivier@aixmarseille.com>, and adapted from spca50x driver."
                "Thanks you, spca50x team, it was easy to port your driver on this cam! "));
        return (GP_OK);
}


#if 0
/*
 * This function probes the camera to get all the storages media
 * supported (sdram, flash, card)
 *
 * Status: Working but not used
 */
static int enigma13_detect_storage_type (Camera *camera)
{
        int i;
        char buf[3];

        for (i=0;i<3;i++)
        {
                CHECK (gp_port_usb_msg_read (camera->port, 0x28, 0x0000,
                                        i, &buf[i], 0x01));           
        }
        gp_log(GP_LOG_DEBUG, "enigma13","Camera storage information sdram: 0x%x flash 0x%x card: 0x%x\n"
                        , buf[0], buf[1], buf[2]);
        return GP_OK;
}
#endif





/*
 * This function deletes all the images
 * supported (sdram, flash, card)
 *
 * Status: not verified 
 */
static int
enigma13_flash_delete_all(CameraFilesystem *fs, const char *folder, void *data,
                 GPContext *context)
{
   Camera *cam;
   gp_log(GP_LOG_DEBUG, "enigma13","Delete all files");
   cam = data;
   CHECK (gp_port_usb_msg_write (cam->port, 0x52, 0x0, 0x0, NULL, 0x0) );
   return GP_OK;                             
}




/*
 * This function waits camera is ready
 *
 * Status: Not sure what it realy does, but the camera replies
 * Can this be some kind of ping for keepalive, or realy a ready status ?
 */
static int enigma13_wait_for_ready(Camera *camera)
{
        int timeout = ENIGMA13_WAIT_FOR_READY_TIMEOUT_S;
        char ready = 1;
        while (timeout--) {
                sleep(1);
                CHECK (gp_port_usb_msg_read (camera->port,
                              0x21, 0x0000, 0x0000,
                              (char*)&ready, 0x01));
                if (ready==0)
                        return GP_OK;
        }
        return GP_ERROR;
}



#if 0
/*
 * Get the number of images in cam
 * 
 * Status: Should work, but not used as enigma13_get_TOC does all.
 *
 */
static int enigma13_get_filecount (Camera *camera, int *filecount)
{
        uint16_t response = 0;
        CHECK(enigma13_wait_for_ready(camera));
        CHECK (gp_port_usb_msg_read (camera->port,
                             0x54, 0x0000, 0x0000,
                             (char*)&response, 0x02));
        LE16TOH (response);
        *filecount = response;
        return GP_OK;
}
#endif




/*
 * Get the table of contents (directory) from the cam 
 *
 * Verified: Yes
 */
static int enigma13_get_toc(Camera *camera, int *filecount, char** toc)
{
        char* flash_toc=NULL;
        int toc_size = 0;
        char buf[10];
        uint16_t response = 0;
        int ret=1;

        CHECK(enigma13_wait_for_ready(camera));
        CHECK (gp_port_usb_msg_read (camera->port,
                             0x54, 0x0000, 0x0000,
                             (char*)&response, 0x02));
        LE16TOH (response);
        *filecount = response;

        /* Calc toc size */
        toc_size = (response) * 0x20;

        if (toc_size % 0x200 != 0)
           toc_size = ((toc_size / 0x200) + 1) * 0x200;

      CHECK(enigma13_wait_for_ready(camera));

        CHECK (gp_port_usb_msg_write (camera->port, 0x54,
                           response, 0x0001,
                          NULL, 0x0000));
        /* Wait until cam is ready to send the T.O.C */
      usleep( ENIGMA13_WAIT_TOC_DELAY_MS);

        CHECK (gp_port_usb_msg_read (camera->port, 0x21,
                           0x0000, 0x0000,
                          buf, 0x01));
        if (buf[0]!=0x41) return GP_ERROR;

        CHECK (gp_port_usb_msg_read (camera->port, 0x21,
                           0x0000, 0x0002,
                          buf, 0x01));
        if (buf[0]!=0x01) return GP_ERROR;


       flash_toc = (char*)malloc(toc_size);
       if (!flash_toc)
                return GP_ERROR_NO_MEMORY;

        ret=gp_port_read (camera->port, flash_toc, toc_size);
        *toc= flash_toc;
                        gp_log(GP_LOG_DEBUG, "enigma13","Byte transferred :%d ", ret);
        return ret;

}


/*
 * Function that downloads image
 *
 * Camera camera  : camera structure
 * int    index   : image index ( in gphoto point of view) -1 for real index
 * char*  toc     : pointer to toc
 * char** img_buf : returned image data
 * int* img_size      : returned image data size  
 *
 */
static int enigma13_download_img(Camera *camera, char *toc, int index, char **img_data, int *img_size)
{
        uint8_t *p;
      uint32_t file_size = 0, aligned_size = 0;
        char* buf=NULL; 
        int align=0;
        char  retbuf[2];

        gp_log(GP_LOG_DEBUG, "enigma13","DOWNLOADING IMAGE NO %d",index);


        /* Offset for image informations .
           Each image has 16 bytes for name and 16 for size, and others*/
      p = toc + (index*2)*32;



        /* real size from toc*/
        aligned_size = file_size =
                  (p[0x1c] & 0xff)
                + (p[0x1d] & 0xff) * 0x100
                + (p[0x1e] & 0xff) * 0x10000;


       CHECK (gp_port_usb_msg_read (camera->port, 0x23,
                           0x0000, 0x64,
                         retbuf, 0x01));
       if (retbuf[0]==0x20){
        align=ENIGMA13_BLK_CARD_ALIGN;
        gp_log(GP_LOG_DEBUG, "enigma13"," Image from card, alignement is set to %d bytes ",align);
       } 
       else if (retbuf[0]==0x10){
        align=ENIGMA13_BLK_FLASH_ALIGN;
        gp_log(GP_LOG_DEBUG, "enigma13"," Image from flash, alignement is set to %d bytes",align);
       } else {
        return GP_ERROR;
       }



        if (file_size % align != 0)
                aligned_size = ((file_size / align) + 1) * align;

        buf = (char*) malloc (aligned_size);
        if (!buf)
                return GP_ERROR_NO_MEMORY;


        CHECK (gp_port_usb_msg_write (camera->port,
               0x54, index+1, 2, NULL, 0x00));
      usleep(ENIGMA13_WAIT_IMAGE_READY_MS);


        CHECK (gp_port_usb_msg_read (camera->port, 0x21,
                           0x0000, 0x0000,
                          buf, 0x01));
        if (buf[0]!=0x41) return GP_ERROR;

       CHECK (gp_port_usb_msg_read (camera->port, 0x21,
                           0x0000, 0x0002,
                          buf, 0x01));
        if (buf[0]!=0x01) return GP_ERROR;

       CHECK (gp_port_usb_msg_read (camera->port, 0x21,
                           0x0000, 0x0002,
                          buf, 0x01));
        if (buf[0]!=0x01) return GP_ERROR;

        gp_log(GP_LOG_DEBUG, "enigma13","READY FOR TRANSFER");
        CHECK (gp_port_read (camera->port, buf, aligned_size));

        *img_data=buf;
        *img_size=file_size;

        return GP_OK;

}








/*
 * GPHOTO list files
 */

static int file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
            void *data, GPContext *context)
{
      Camera *camera = data;
      int   i, numpics;
        char tmp[20];

        CHECK(enigma13_get_toc(camera,&numpics,&enigma13_static_toc));

      for ( i=0; i < numpics; i=i+2 ) {
                sprintf(tmp,"sunp%04d.jpg",(i/2));
            gp_list_append( list, tmp, NULL);
      }
      return (GP_OK);
}






/*
 * File operations 
 */
static int
get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
             CameraFileType type, CameraFile *file, void *data,
             GPContext *context)
{


      Camera *camera = data;
        int image_no, result;
      //int i, ret, numpics;


      char* img_data=NULL;
        int   img_size=-1;

        image_no = gp_filesystem_number(fs, folder, filename, context);
        gp_file_set_name (file, filename);

        gp_log(GP_LOG_DEBUG, "enigma13","Index of image %d is %s",image_no, filename);


        switch (type) {

        case GP_FILE_TYPE_NORMAL:
        {
                gp_log(GP_LOG_DEBUG, "enigma13","Downloading raw image");

                CHECK(enigma13_download_img(camera, enigma13_static_toc, image_no, &img_data, &img_size));
                result = gp_file_append( file, img_data, img_size);
 
            break;
      }


      default:
                result = GP_ERROR_NOT_SUPPORTED;
            break;
        }

        if (result < 0)
                return result;
        return (GP_OK);
}

int
camera_abilities (CameraAbilitiesList *list) 
{
      CameraAbilities a;

      memset(&a, 0, sizeof(a));
      strcpy(a.model,   "DigitalDream:Enigma1.3");
      a.status = GP_DRIVER_STATUS_EXPERIMENTAL;
      a.port            = GP_PORT_USB;
      a.speed[0]        = 0;
      a.usb_vendor            = 0x05da;
      a.usb_product           = 0x1018;
      a.operations            =  GP_OPERATION_NONE;
      a.file_operations =  GP_FILE_OPERATION_NONE;
      a.folder_operations     =  GP_FOLDER_OPERATION_DELETE_ALL;
      gp_abilities_list_append(list, a);
      return (GP_OK);
}

int
camera_id (CameraText *id) 
{
      strcpy(id->text, "Digital Dream Enigma 1.3");
      return (GP_OK);
}

static CameraFilesystemFuncs fsfuncs = {
      .file_list_func = file_list_func,
      .get_file_func = get_file_func,
      .delete_all_func = enigma13_flash_delete_all
};

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

        camera->functions->about        = enigma13_about;

      CHECK(gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera));
      CHECK(gp_port_get_settings( camera->port, &settings));
        settings.usb.inep = 0x82;
        settings.usb.outep = 0x03;
        settings.usb.config = 1;
        settings.usb.interface = 0;
        settings.usb.altsetting = 0;
        CHECK(gp_port_set_timeout (camera->port, ENIGMA13_USB_TIMEOUT_MS));
      CHECK(gp_port_set_settings( camera->port, settings));
      return GP_OK;


}






Generated by  Doxygen 1.6.0   Back to index