Logo Search packages:      
Sourcecode: libgphoto2 version File versions  Download package

blink2.c

/* blink2.c
 *
 * Copyright  2003 Marcus Meissner <marcus@jet.franken.de>
 *
 * 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>

#ifdef HAVE_LIBJPEG
# include <jpeglib.h>
#endif

#include <gphoto2-library.h>
#include <gphoto2-port-log.h>
#include <gphoto2-result.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 BLINK2_GET_NUMPICS          0x08
#define BLINK2_GET_MEMORY           0x0a
#define BLINK2_GET_DIR              0x0d
#define BLINK2_INIT_CAPTURE         0x0e
#define BLINK2_DELETE_ALL           0x12
#define BLINK2_CHECK_CAPTURE_FINISH 0x16
#define BLINK2_SET_EXPOSURE_COUNT   0x17
#define BLINK2_GET_FIRMWARE_ID            0x18

static int
blink2_getnumpics(
    GPPort *port, GPContext *context,int *numpics
) {
    char buf[6];
    int ret;
    
    ret = gp_port_usb_msg_read(port, BLINK2_GET_NUMPICS, 0x03, 0, buf, 2);
    if (ret<GP_OK)
      return ret;
    *numpics = (buf[0]<<8) | buf[1];
    return GP_OK;
}

#ifdef HAVE_LIBJPEG
/* for the jpeg decompressor source manager. */
static void _jpeg_init_source(j_decompress_ptr cinfo) { }

static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
    fprintf(stderr,"(), should not get here.\n");
    return FALSE;
}

static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
    fprintf(stderr,"(%ld), should not get here.\n",num_bytes);
}

static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
    fprintf(stderr,"(desired=%d), should not get here.\n",desired);
    return FALSE;
}
static void _jpeg_term_source(j_decompress_ptr cinfo) { }
#endif

static int
file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
            void *data, GPContext *context)
{
      Camera *camera = data;
      int   i, ret, numpics, bytes;
      unsigned char     *xbuf, buf[8];

      ret = blink2_getnumpics( camera->port, context, &numpics );
      if (ret < GP_OK) return ret;

      bytes = ((8*(1+numpics))+0x3f) & ~0x3f;
      xbuf = malloc(bytes);
      ret = gp_port_usb_msg_read( camera->port,BLINK2_GET_DIR,0x03,0,buf,1 );
      if (ret < GP_OK)  {
            free(xbuf);
            return ret;
      }
      ret = gp_port_read( camera->port, xbuf, bytes);
      if (ret < GP_OK) {
            free(xbuf);
            return ret;
      }
      for ( i=0; i < numpics; i++) {
            char name[20];
            if (xbuf[8*(i+1)])
                  sprintf( name, "image%04d.avi", i);
            else
                  sprintf( name, "image%04d.pnm", i);
            gp_list_append( list, name, NULL);
      }
      free(xbuf);
      return (GP_OK);
}

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, bytes;
      unsigned char     *xbuf, buf[8];

      struct xaddr {
            unsigned int type, start,len;
      } *addrs;

      ret = blink2_getnumpics( camera->port, context, &numpics );
      if (ret < GP_OK) return ret;
      gp_log(GP_LOG_DEBUG, "blink2","numpics is %d", numpics);
      bytes = ((8*(1+numpics))+0x3f) & ~0x3f;
      xbuf = malloc(bytes);
      if (!xbuf)
            return GP_ERROR_NO_MEMORY;
      addrs = (struct xaddr*)malloc(sizeof(struct xaddr)*numpics);
      if (!addrs) {
            free(xbuf);
            return GP_ERROR_NO_MEMORY;
      }
      ret = gp_port_usb_msg_read( camera->port,BLINK2_GET_DIR,0x03,0,buf,1 );
      if (ret < GP_OK) {
            free(addrs);
            free(xbuf);
            return ret;
      }
      ret = gp_port_read (camera->port, xbuf, bytes);
      if (ret < GP_OK) {
            free(addrs);
            free(xbuf);
            return ret;
      }
      for ( i=0; i < numpics; i++) {
            int end, start;

            start = (xbuf[8*i+ 5] << 16) |
                  (xbuf[8*i+ 6] <<  8) |
                  (xbuf[8*i+ 7]);
            end =       (xbuf[8*i+13] << 16) |
                  (xbuf[8*i+14] <<  8) |
                  (xbuf[8*i+15]);
            addrs[i].start = start;
            addrs[i].len = (end-start)/4;
            addrs[i].type = xbuf[8*(i+1)];
            gp_log(GP_LOG_DEBUG, "blink2","%d - %d", start, (end-start)/4);
      }
      free(xbuf);

        image_no = gp_filesystem_number(fs, folder, filename, context);
        if(image_no < 0) {
            free(addrs);
                return image_no;
      }
        gp_file_set_name (file, filename);
        switch (type) {
        case GP_FILE_TYPE_NORMAL:
#ifdef HAVE_LIBJPEG
{
            char *convline,*convline2,*rawline;
            unsigned char     *jpegdata;
            unsigned int start, len, i, pitch;
            int curread, ret;
            struct jpeg_decompress_struct dinfo;
            struct jpeg_source_mgr        xjsm;
            struct jpeg_error_mgr         jerr;

            memset( buf, 0, sizeof(buf));
            if (addrs[image_no].type)
                  gp_file_set_mime_type (file, GP_MIME_AVI);
            else
                  gp_file_set_mime_type (file, GP_MIME_JPEG);
            start = addrs[image_no].start;
            len = addrs[image_no].len;
            jpegdata = (unsigned char*)malloc (len*8);
            if (!jpegdata) {
                  result = GP_ERROR_NO_MEMORY;
                  break;
            }
            buf[0] = (start >> 24) & 0xff;
            buf[1] = (start >> 16) & 0xff;
            buf[2] = (start >>  8) & 0xff;
            buf[3] =  start        & 0xff;
            buf[4] = (len >> 24) & 0xff;
            buf[5] = (len >> 16) & 0xff;
            buf[6] = (len >>  8) & 0xff;
            buf[7] =  len        & 0xff;
            result = gp_port_usb_msg_write (camera->port,BLINK2_GET_MEMORY,0x03,0,buf,8);
            if (result < GP_OK)
                  break;
            len   *= 8;
            curread  = 0;
            do {
                  int res;
                  res = gp_port_read (camera->port, jpegdata+curread, len );
                  if (res < GP_OK) {
                        result = GP_OK;
                        break;
                  }
                  curread += res;
            } while (curread<=len);

            memset( &dinfo, 0, sizeof(dinfo));
            xjsm.next_input_byte    = jpegdata;
            xjsm.bytes_in_buffer    = len;
            xjsm.init_source  = _jpeg_init_source;
            xjsm.fill_input_buffer  = _jpeg_fill_input_buffer;
            xjsm.skip_input_data    = _jpeg_skip_input_data;
            xjsm.resync_to_restart  = _jpeg_resync_to_restart;
            xjsm.term_source  = _jpeg_term_source;
            dinfo.err         = jpeg_std_error(&jerr);
            jpeg_create_decompress(&dinfo);
            dinfo.src         = &xjsm;
            ret = jpeg_read_header(&dinfo,TRUE);
            if (ret != JPEG_HEADER_OK)
                  break;
            dinfo.out_color_space = JCS_RGB;
            jpeg_start_decompress(&dinfo);

            pitch = (dinfo.output_width*dinfo.output_components+3)&~3;

            rawline = malloc(pitch);
            convline = malloc(dinfo.output_width*2*3);
            convline2 = malloc(dinfo.output_width*2*2*3);
            if (ret != JPEG_HEADER_OK)
                  return GP_ERROR;
            {
                  char foo[30];
                  sprintf(foo,"P6\n%d %d 255\n",dinfo.output_width, dinfo.output_height*2);
                  gp_file_append (file, foo, strlen(foo));
            }
            for (i = 0; i < dinfo.output_height ; i++ ) {
                  int j;
                  JSAMPROW row[1];
                  JSAMPARRAY arr = row;

                  row[0] = (JSAMPROW)rawline;
                  jpeg_read_scanlines(&dinfo,arr,1);

                  memcpy(convline+((dinfo.output_width/16-1)*16+8)*3, rawline+((dinfo.output_width/16-1)*16+8)*3, 8*3);
                  memcpy(convline+pitch/2, rawline, 8*3);
                  for (j=0;j<(dinfo.output_width/16-1);j++) {
                        if ((j&1) == 0)
                              memcpy(convline+((j/2)*16)*3,rawline+(j*16+8)*3,16*3);
                        else
                              memcpy(convline+pitch/2+((j/2)*16+8)*3,rawline+(j*16+8)*3,16*3);
                  }
                  for (j=0;j<dinfo.output_width*2;j++) {
                        memcpy(convline2+ j*2*3   , convline+j*3,3);
                        memcpy(convline2+(j*2+1)*3, convline+j*3,3);
                  }
                  gp_file_append (file, convline2, pitch*2);
            }
            free(convline2);
            free(convline);
            free(rawline);
            free(jpegdata);
            gp_file_set_mime_type (file, GP_MIME_PPM);
            jpeg_destroy_decompress(&dinfo);
            break;
      }
#else
      /* fall through to raw mode if no libjpeg */
#endif
        case GP_FILE_TYPE_RAW: {
            char buf2[4096];
            unsigned int start, len;
            int curread;
            memset( buf, 0, sizeof(buf));
            
            if (addrs[image_no].type)
                  gp_file_set_mime_type (file, GP_MIME_AVI);
            else
                  gp_file_set_mime_type (file, GP_MIME_JPEG);

            start = addrs[image_no].start;
            len = addrs[image_no].len;
            buf[0] = (start >> 24) & 0xff;
            buf[1] = (start >> 16) & 0xff;
            buf[2] = (start >>  8) & 0xff;
            buf[3] =  start        & 0xff;
            buf[4] = (len >> 24) & 0xff;
            buf[5] = (len >> 16) & 0xff;
            buf[6] = (len >>  8) & 0xff;
            buf[7] =  len        & 0xff;
            result = gp_port_usb_msg_write(camera->port,BLINK2_GET_MEMORY,0x03,0,buf,8);
            if (result < GP_OK)
                  break;
            len = len*8;
            do {
                  curread = 4096;
                  if (curread > len) curread = len;
                  curread = gp_port_read( camera->port, buf2, curread);
                  if (curread < GP_OK) {
                        result = GP_OK;
                        break;
                  }
                  len -= curread;
                  result = gp_file_append( file, buf2, curread);
                  if (result < GP_OK)
                        break;
            } while (len>0);
                break;
        }
      default:
                result = GP_ERROR_NOT_SUPPORTED;
            break;
        }
      free(addrs);
        if (result < 0)
                return result;
        return (GP_OK);
}

static int
delete_all_func (CameraFilesystem *fs, const char *folder, void *data,
                 GPContext *context)
{
      Camera *camera = data;
      int ret;
      char buf[1];

      ret = gp_port_usb_msg_read( camera->port, BLINK2_DELETE_ALL, 0x03, 0, buf, 1);
      if (ret < GP_OK)
            return ret;
        return (GP_OK);
}

static int
camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path,
                GPContext *context)
{
      int oldnumpics, numpics, ret;
      char buf[1];
      
      ret = blink2_getnumpics (camera->port, context, &oldnumpics);
      if (ret < GP_OK)
            return ret;

      ret = gp_port_usb_msg_read( camera->port, BLINK2_INIT_CAPTURE, 0x03, 0, buf, 1);
      if (ret < GP_OK)
            return ret;
      do {
            ret = gp_port_usb_msg_read( camera->port, BLINK2_CHECK_CAPTURE_FINISH, 0x03, 0, buf, 1);
            if (ret < GP_OK)
                  return ret;
            sleep(1);
      } while (buf[1] == 0x00);

      ret = blink2_getnumpics (camera->port, context, &numpics);
      if (ret < GP_OK)
            return ret;
      if (numpics == oldnumpics)
            return (GP_ERROR);
        strcpy (path->folder,"/");
        sprintf (path->name,"image%04d.pnm",numpics-1);
        return (GP_OK);
}


int
camera_abilities (CameraAbilitiesList *list) 
{
      CameraAbilities a;

      memset(&a, 0, sizeof(a));
      strcpy(a.model,   "SiPix:Blink 2");
      a.status = GP_DRIVER_STATUS_EXPERIMENTAL;
      a.port            = GP_PORT_USB;
      a.speed[0]        = 0;
      a.usb_vendor            = 0x0c77;
      a.usb_product           = 0x1011;
      a.operations            =  GP_OPERATION_CAPTURE_IMAGE;
      a.file_operations =  GP_FILE_OPERATION_NONE;
      a.folder_operations     =  GP_FOLDER_OPERATION_DELETE_ALL;
      gp_abilities_list_append(list, a);

      a.usb_product           = 0x1010;
      strcpy(a.model, "SiPix:Snap");
      gp_abilities_list_append(list, a);

      a.usb_product           = 0x1015;
      strcpy(a.model, "SiPix:CAMeleon");
      gp_abilities_list_append(list, a);

      return (GP_OK);
}

int
camera_id (CameraText *id) 
{
      strcpy(id->text, "SiPix Blink2");
      return (GP_OK);
}

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

int
camera_init (Camera *camera, GPContext *context) 
{
      char buf[6];
      int ret;
      GPPortSettings settings;

        camera->functions->capture              = camera_capture;

      gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
      gp_port_get_settings( camera->port, &settings);
      settings.usb.interface = 0;
      settings.usb.altsetting = 0;
      ret = gp_port_set_settings (camera->port, settings);
      if (ret < GP_OK) return ret;

      ret = gp_port_usb_msg_read( camera->port, BLINK2_GET_FIRMWARE_ID, 0x03, 0, buf, 6);
      if (ret < GP_OK)
            return ret;
      ret = gp_port_usb_msg_read( camera->port, 0x04, 0x03, 0, buf, 1);
      if (ret < GP_OK)
            return ret;
      return GP_OK;
}

Generated by  Doxygen 1.6.0   Back to index