summaryrefslogtreecommitdiff
path: root/camlibs/iclick
diff options
context:
space:
mode:
authorTheodore Kilgore <kilgota@auburn.edu>2004-11-26 07:45:05 +0000
committerTheodore Kilgore <kilgota@auburn.edu>2004-11-26 07:45:05 +0000
commitc7458bc61b5b7adda0f512f12fa6763dcb1c02b6 (patch)
tree17eebe77e05db726e0a59b24bb2d394c48fefa8c /camlibs/iclick
parent054e42dc671d228582cd82643fedd8771b549f79 (diff)
downloadlibgphoto2-c7458bc61b5b7adda0f512f12fa6763dcb1c02b6.tar.gz
First check-in.
git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@7397 67ed7778-7388-44ab-90cf-0a291f65f57c
Diffstat (limited to 'camlibs/iclick')
-rw-r--r--camlibs/iclick/ChangeLog3
-rw-r--r--camlibs/iclick/Makefile.am13
-rw-r--r--camlibs/iclick/README78
-rw-r--r--camlibs/iclick/iclick.c176
-rw-r--r--camlibs/iclick/iclick.h94
-rw-r--r--camlibs/iclick/library.c370
6 files changed, 734 insertions, 0 deletions
diff --git a/camlibs/iclick/ChangeLog b/camlibs/iclick/ChangeLog
new file mode 100644
index 000000000..b9d4a2649
--- /dev/null
+++ b/camlibs/iclick/ChangeLog
@@ -0,0 +1,3 @@
+2004-11-26 Theodore Kilgore <kilgota@auburn.edu>
+
+ * *.[c,h]: First check-in.
diff --git a/camlibs/iclick/Makefile.am b/camlibs/iclick/Makefile.am
new file mode 100644
index 000000000..6e13c0a1d
--- /dev/null
+++ b/camlibs/iclick/Makefile.am
@@ -0,0 +1,13 @@
+camlib_LTLIBRARIES = libgphoto2_iclick.la
+
+INCLUDES = \
+ -I$(top_srcdir)/intl \
+ -I$(top_srcdir)/libgphoto2_port \
+ -I$(top_srcdir)/libgphoto2_port/libgphoto2_port \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/libgphoto2 \
+ -I$(top_builddir)/libgphoto2
+
+libgphoto2_iclick_la_SOURCES = library.c iclick.c iclick.h
+libgphoto2_iclick_la_LDFLAGS = -module -avoid-version
+libgphoto2_iclick_la_LIBADD = $(top_builddir)/libgphoto2/libgphoto2.la
diff --git a/camlibs/iclick/README b/camlibs/iclick/README
new file mode 100644
index 000000000..af5112307
--- /dev/null
+++ b/camlibs/iclick/README
@@ -0,0 +1,78 @@
+/* This is a supplemental README file for libgphoto2/camlibs/iclick,
+ * another camera fro S&Q Technologies.
+ * Integral part of the libgphoto2/camlibs/iclick library source and is
+ * distributed with that source under the LGPL license. a copy of which
+ * license may be seen in any of the source files in libgphoto2/camlibs/iclick,
+ * or in the head directory of libgphoto2. This README and the rest of the
+ * library are copyright Stephen Pollei <stephen_pollei@comcast.net> and
+ * Theodore Kilgore <kilgota@auburn.edu>.
+ */
+
+**************************************************************************
+BIG FAT WARNING
+
+This library is in the process of being written, and at present is of
+limited functionality. As far as we know, it will do what we say it will do,
+and it will also not do what we say it will not do. Therefore, please read
+the following discussion of the features which are supported at present and
+the features which are not supported! We hope to be able to do more, and if
+you have one of these cameras we hope that you will look for anticipated
+updates at the CVS tree of libgphoto2, found at <gphoto.sourceforge.net>.
+***************************************************************************
+
+
+This library has been written specifically to support the iClick Pro 5X,
+a simple and inexpensive camera. A brief description of the camera may be
+found at <iclickphoto.com>.
+
+The camera has the USB Vendor:Product ID of 0x2770:0x9153, which would
+seem to indicate that it contains a chip from S&Q Technologies, Taiwan. The
+same company makes the sq905 chipset which is in many entry-level cameras;
+the chip in this camera is probably an sq915 chip, and it uses a different
+communication protocol. Probably, any other cameras with this chip inside
+will also work with this camera library, but we do not know that at this
+time.
+
+The camera has a flash, takes 640x480 pictures, and has a slot for a memory
+card. Without the memory card, it will hold 16 still photos, and with a
+memory card (maximum size is advertised as 128MB) it will clearly hold many
+more. A memory card has been tested with the camera and seems to work
+without any problems.
+
+The 640x480 photos can be blown up to a larger size by the OEM driver which
+comes with the camera. It is stated in the documentation that this is done
+by "interpolation" meaning that the actual amount of data is 640x480. The
+format of the data from the camera is a standard Bayer format, and this
+driver should download such photos. The photos look fairly sharp for
+640x480; the color mapping could however be improved by postprocessing. For
+now, we recommend the use of GIMP or the old xview ("xv") program to do that
+after you download the photos.
+
+It is important to note that the construction of the hardware itself will
+not easily support downloading of random photos, which may present severe
+incompatibility with a GUI program such as gtkam, digikam, or similar.
+Thus, the user is advised to use the command "gphoto2 -P" to dump all photos
+on the camera into a directory. After this, the user can inspect at leisure
+the photos on the hard drive and can decide which ones to keep and which
+ones to delete. We repeat: We do not advise the use of a GUI frontend at
+this time, because we cannot guarantee that it will work.
+
+The camera also has two other modes of operation, which this driver does not
+support. There is a "video clip" feature which will shoot a number of
+frames. Apparently, these frames are then saved in some kind of JPEG format,
+and the size is given in the JPEG headers in the data as 320x240. This
+feature is at present NOT SUPPORTED. So please do not try to use it and
+especially do not try to mix clips with still photos on the camera. The fact
+that the clips are not of a fixed, given size will mess up your download.
+
+There is also a webcam feature. Gphoto2-libgphoto2 is in general not
+designed to support streaming video, which in general requires a kernel
+module. Abstractly speaking, the command "gphoto2 --capture-preview" can use
+the webcam mode to cause a tethered camera to snap a photo. This also we do
+not support at present. So if you make it work be sure to let us know.
+
+Taking the above caveats fully into consideration, we hope that you enjoy
+your experience with this camera.
+
+Stephen Pollei and Theodore Kilgore
+November 25, 2004. \ No newline at end of file
diff --git a/camlibs/iclick/iclick.c b/camlibs/iclick/iclick.c
new file mode 100644
index 000000000..80355b82d
--- /dev/null
+++ b/camlibs/iclick/iclick.c
@@ -0,0 +1,176 @@
+/*
+ * iclick.c
+ *
+ * Here, the functions which are needed to get data from the camera.
+ *
+ * Copyright (c) 2004 Theodore Kilgore <kilgota@auburn.edu>,
+ * Stephen Pollei <stephen_pollei@comcast.net>.
+ * Camera library support under libgphoto2.1.1 for camera(s)
+ * with chipset from Service & Quality Technologies, Taiwan.
+ * The chip supported by this driver is presumed to be the SQ915.
+ *
+ * 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.
+ *
+ * Licensed under GNU Lesser General Public License, as part of Gphoto
+ * camera support project. For a copy of the license, see the file
+ * COPYING in the main source tree of libgphoto2.
+ */
+
+#include <config.h>
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <math.h>
+#ifdef OS2
+#include <db.h>
+#endif
+
+#include <gphoto2.h>
+#include <gphoto2-port.h>
+#include "iclick.h"
+
+#define GP_MODULE "iclick"
+
+#define SQWRITE gp_port_usb_msg_write
+#define SQREAD gp_port_usb_msg_read
+
+#define zero "\x0"
+
+/*
+static unsigned char *
+icl_read_data (GPPort *port, unsigned char *data, int size)
+{
+ gp_port_read (port, data, size);
+ return GP_OK;
+}
+*/
+
+int icl_access_reg (GPPort *port, enum icl_cmnd_type reg)
+{
+ SQWRITE (port, 0x0c, reg,
+ (CONFIG == reg) ? CONFIG_I : 0,
+ NULL, 0); /* Access a register */
+ return GP_OK;
+}
+
+int
+icl_init (GPPort *port, CameraPrivateLibrary *priv)
+{
+ int i;
+ static unsigned char dummy_buf[0x28000];
+ unsigned char *catalog = malloc(0x8000);
+ unsigned char *catalog_tmp;
+
+ priv->model=SQ_MODEL_ICLICK;
+
+
+ if (!catalog) return GP_ERROR_NO_MEMORY;
+
+
+ icl_reset (port);
+
+ icl_access_reg(port, CONFIG); /* Access config */
+ gp_port_read(port, catalog, 0x8000);
+ /* Config data is in lines of 16 bytes. Each photo uses two lines. */
+ icl_read_picture_data(port, dummy_buf, 0x28000);
+ icl_reset (port);
+
+ /* Photo list starts with line 0040. List terminates when we
+ * the first entry of an even-numbered line is zero. */
+ for (i=0; i<0x8000 && catalog[i+64] ; i+=32) ;
+ priv->nb_entries = i>>5;
+ catalog_tmp = realloc(catalog, i);
+ if (i) {
+ if (catalog_tmp) priv->catalog = catalog_tmp;
+ else priv->catalog = catalog;
+ } else {
+ priv->catalog = NULL; /* We just have freed catalog_tmp */
+ }
+
+ icl_reset (port);
+
+ priv->data_offset = -1;
+
+ return GP_OK;
+}
+
+int
+icl_get_start (CameraPrivateLibrary *priv, int entry)
+{
+ int start = 0x4b100 * entry;
+ return start;
+}
+
+int
+icl_get_size (CameraPrivateLibrary *priv, int entry)
+{
+ return 0x4b100;
+}
+
+
+int
+icl_get_width_height (CameraPrivateLibrary *priv, int entry, int *w, int *h)
+{
+ *w = 640;
+ *h = 480;
+ return GP_OK;
+}
+
+
+int
+icl_rewind (GPPort *port, CameraPrivateLibrary *priv)
+{
+ static unsigned char dummy_buf[0x30000];
+
+ GP_DEBUG("REWIND cam's data pointer");
+
+ /* One has to read the catalog to rewind the data stream...
+ * I don't know if it's by design.
+ * There ought to be something better to do... :-/
+ */
+
+
+ icl_access_reg(port, CONFIG); /* Access model */
+
+ icl_read_picture_data(port, dummy_buf, 0x30000);
+
+ icl_reset (port);
+ icl_access_reg(port, DATA); /* Access photo data */
+
+ priv->data_offset = icl_get_start (priv, 0);
+
+ return GP_OK;
+}
+
+int
+icl_reset (GPPort *port)
+{
+ icl_access_reg(port, CLEAR); /* Release current register */
+
+ return GP_OK;
+}
+
+unsigned char *
+icl_read_picture_data (GPPort *port, unsigned char *data, int size )
+{
+ int remainder = size % 0x8000;
+ int offset = 0;
+
+ while ((offset + 0x8000) <= size) {
+ gp_port_read (port, data + offset, 0x8000);
+ offset += 0x8000;
+ }
+ if (remainder)
+ gp_port_read (port, data + offset, remainder);
+
+ return GP_OK;
+}
+
+
diff --git a/camlibs/iclick/iclick.h b/camlibs/iclick/iclick.h
new file mode 100644
index 000000000..2b27a93ef
--- /dev/null
+++ b/camlibs/iclick/iclick.h
@@ -0,0 +1,94 @@
+/*
+ * iclick.c
+ *
+ * Here, the functions which are needed to get data from the camera.
+ *
+ * Copyright (c) 2004 Theodore Kilgore <kilgota@auburn.edu>,
+ * Stephen Pollei <stephen_pollei@comcast.net>.
+ * Camera library support under libgphoto2.1.1 for camera(s)
+ * with chipset from Service & Quality Technologies, Taiwan.
+ * The chip supported by this driver is presumed to be the SQ915.
+ *
+ * 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.
+ *
+ * Licensed under GNU Lesser General Public License, as part of Gphoto
+ * camera support project. For a copy of the license, see the file
+ * COPYING in the main source tree of libgphoto2.
+ */
+
+
+
+#ifndef __ICLICK_H__
+#define __ICLICK_H__
+
+#include <libgphoto2_port/gphoto2-port.h>
+
+/* A 'picture' is a single standalone picture.
+ * A 'clip' is an autoshoot clip.
+ * A 'frame' is a single a picture out of a clip.
+ * An 'entry' corresponds to a line listed in the camera's configuration data,
+ * part of which is a rudimentary allocation table (the 'catalog').
+ * An entry, therefore, may be either a picture or a clip.
+ * We reserve the word 'file' for the user fetchable file,
+ * that is, a picture or a frame.
+ */
+
+
+typedef enum {
+ SQ_MODEL_POCK_CAM,
+ SQ_MODEL_PRECISION,
+ SQ_MODEL_MAGPIX,
+ SQ_MODEL_ICLICK,
+ SQ_MODEL_DEFAULT
+} SQModel;
+
+
+
+struct _CameraPrivateLibrary {
+ SQModel model;
+ unsigned char *catalog;
+ int nb_entries;
+ int data_offset;
+};
+
+
+// #define ID 0xf0
+enum icl_cmnd_type {
+ CONFIG =0x20,
+ DATA =0x30,
+ CLEAR =0xa0,
+ CAPTURE=0x61,
+};
+
+enum icl_index_type {
+ CONFIG_I =0x300,
+ DATA_I =0x000,
+ CLEAR_I =0x000,
+ CAPTURE_I=0x000,
+};
+
+
+int icl_access_reg (GPPort *, enum icl_cmnd_type);
+
+#if 0
+#define icl_access_reg(iar_port, iar_kind) do { \
+ SQWRITE (iar_port, 0x0c, iar_kind, iar_kind##_I, NULL, 0); \
+ } while (0)
+#endif
+
+int icl_reset (GPPort *);
+int icl_rewind (GPPort *, CameraPrivateLibrary *);
+int icl_init (GPPort *, CameraPrivateLibrary *);
+unsigned char *icl_read_picture_data (GPPort *, unsigned char *data, int size);
+
+/* Those functions don't need data transfer with the camera */
+
+int icl_get_start (CameraPrivateLibrary *, int entry);
+int icl_get_size (CameraPrivateLibrary *, int entry);
+int icl_get_width_height (CameraPrivateLibrary *, int entry, int *w, int *h);
+
+#endif
+
diff --git a/camlibs/iclick/library.c b/camlibs/iclick/library.c
new file mode 100644
index 000000000..ce5f7c472
--- /dev/null
+++ b/camlibs/iclick/library.c
@@ -0,0 +1,370 @@
+/* library.c
+ *
+ * Copyright (C) 2004 Theodore Kilgore <kilgota@auburn.edu>,
+ * Stephen Pollei <stephen_pollei@comcast.net>.
+ *
+ * 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 <bayer.h>
+#include <gamma.h>
+
+
+#include <gphoto2.h>
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# undef _
+# define _(String) dgettext (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
+
+#include "iclick.h"
+
+#include <gphoto2-port.h>
+
+#define GP_MODULE "iclick"
+
+struct {
+ char *name;
+ CameraDriverStatus status;
+ unsigned short idVendor;
+ unsigned short idProduct;
+} models[] = {
+ {"iClick 5X", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9153},
+ {NULL,0,0}
+};
+
+int
+camera_id (CameraText *id)
+{
+ strcpy (id->text, "iClick 5X");
+
+ return GP_OK;
+}
+
+
+int
+camera_abilities (CameraAbilitiesList *list)
+{
+ int i;
+ CameraAbilities a;
+
+ for (i = 0; models[i].name; i++) {
+ memset (&a, 0, sizeof(a));
+ strcpy (a.model, models[i].name);
+ a.status = models[i].status;
+ a.port = GP_PORT_USB;
+ a.speed[0] = 0;
+ a.usb_vendor = models[i].idVendor;
+ a.usb_product= models[i].idProduct;
+ if (a.status == GP_DRIVER_STATUS_EXPERIMENTAL)
+ a.operations = GP_OPERATION_NONE;
+ else
+ a.operations = GP_OPERATION_CAPTURE_PREVIEW;
+ a.folder_operations = GP_FOLDER_OPERATION_DELETE_ALL;
+ a.file_operations = GP_FILE_OPERATION_PREVIEW + GP_FILE_OPERATION_RAW;
+ gp_abilities_list_append (list, a);
+ }
+
+ return GP_OK;
+}
+
+static int
+camera_summary (Camera *camera, CameraText *summary, GPContext *context)
+{
+ sprintf (summary->text,_("Your USB camera is an iClick 5X.\n"
+ "The total number of pictures taken is %i\n"),
+
+ camera->pl->nb_entries);
+
+ return GP_OK;
+}
+
+static int camera_manual (Camera *camera, CameraText *manual, GPContext *context)
+{
+ strcpy(manual->text,
+ _(
+ "For cameras with ID 0x2770:0x9153.\n\n"
+ "We do not recommend the use of a GUI program to access\n"
+ "this camera, unless you are just having fun or trying to\n"
+ "see if you can blow a fuse.\n"
+ "If you seriously want your photos, try\n"
+ "gphoto2 -P\n"
+ "from the command line.\n"
+ "Also don't even try to download video clips.\n")
+ );
+
+ return (GP_OK);
+}
+
+
+
+static int
+camera_about (Camera *camera, CameraText *about, GPContext *context)
+{
+ strcpy (about->text, _("iClick 5X driver\n"
+ "Theodore Kilgore <kilgota@auburn.edu>\n"));
+
+ return GP_OK;
+}
+
+/*************** File and Downloading Functions *******************/
+
+
+static int
+file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
+ void *data, GPContext *context)
+{
+ Camera *camera = data;
+ int i;
+ unsigned char buf[1024];
+ GP_DEBUG ("List files in %s\n", folder);
+
+ gp_list_reset (list);
+ for (i = 0; i < camera->pl->nb_entries; i++) {
+ snprintf(buf, sizeof(buf), "img%03i.ppm", i + 1);
+ gp_list_append (list, buf, NULL);
+ }
+
+ 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 entry, w, h; /* frame; */
+ unsigned char *frame_data;
+ unsigned char *ppm, *ptr;
+ unsigned char gtable[256];
+ int start;
+ int datasize, framesize, hdrsize, ppmsize;
+ int nb_frames=1;
+ unsigned char buf[0x8000];
+
+#if 0 /* libgphoto2 likes to search in vain for EXIF data, which isn't there.
+ It's a waste of time, and there should be a way to disable it
+ explicitly. But there isn't. Un-if this if you don't like it,
+ and you can still retrieve the first frame of a video via the
+ frame filename instead. */
+ if (GP_FILE_TYPE_PREVIEW==type)
+ return GP_ERROR_NOT_SUPPORTED;
+#endif
+
+ if (GP_FILE_TYPE_RAW!=type && GP_FILE_TYPE_NORMAL!=type
+ && GP_FILE_TYPE_PREVIEW!=type) {
+
+ return GP_ERROR_NOT_SUPPORTED;
+ }
+
+ /* Get the entry number of the photo on the camera */
+ entry = gp_filesystem_number (camera->fs, folder, filename, context);
+ if (entry < GP_OK)
+ return GP_ERROR_FILE_NOT_FOUND;
+
+ GP_DEBUG ("Download file %s, entry = %d\n",
+ filename, entry);
+
+ if (entry >= camera->pl->nb_entries)
+ return GP_ERROR_FILE_NOT_FOUND;
+
+ /* Fetch entries until the one we need, and toss all but the one we need.
+ * TODO: Either find out how to use the location info in the catalog to
+ * download just the entry needed, or show it is as impossible as it seems.
+ */
+
+ /* Change register to DATA, but only if necessary */
+ if (camera->pl->data_offset == -1) {
+ icl_access_reg(camera->port, DATA);
+
+ /* Camera starts at the first picture.. */
+ camera->pl->data_offset = icl_get_start (camera->pl, 0);
+ }
+
+ start = icl_get_start (camera->pl, entry);
+ datasize = icl_get_size (camera->pl, entry);
+ /* datasize exceeds the actual datasize by 0x100 bytes, which seems to be
+ * 0x100 bytes of filler at the beginning. For now we will treat this extra
+ * 0x100 bytes as junk and just ditch it.
+ */
+
+ GP_DEBUG ("data offset at %d, picture at %d\n", camera->pl->data_offset, start);
+
+ /* Rewind if we're past the requested picture */
+ if (camera->pl->data_offset > start) {
+ icl_rewind(camera->port, camera->pl);
+ }
+
+ /* Seek to the requested picture */
+ while ((camera->pl->data_offset + 0x8000) < start) {
+ icl_read_picture_data(camera->port, buf, 0x8000);
+ camera->pl->data_offset += 0x8000;
+ }
+ if (camera->pl->data_offset < start) {
+ icl_read_picture_data(camera->port, buf, start - camera->pl->data_offset);
+ camera->pl->data_offset = start;
+ }
+
+ /* Retrieve frames */
+ framesize = datasize;
+
+ frame_data = malloc(datasize);
+ icl_read_picture_data(camera->port, frame_data, datasize);
+ camera->pl->data_offset += datasize;
+
+ switch (type) {
+ case GP_FILE_TYPE_PREVIEW:
+ if (icl_get_width_height (camera->pl, entry, &w, &h) >= GP_OK)
+ break; /* Known format, process image */
+ /* No previewing of raw data */
+ free (frame_data);
+ return GP_ERROR_NOT_SUPPORTED;
+ case GP_FILE_TYPE_NORMAL:
+ if (icl_get_width_height (camera->pl, entry, &w, &h) >= GP_OK)
+ break; /* Known format, process image */
+ /* Unsupported format, fallthrough to raw */
+ case GP_FILE_TYPE_RAW:
+ gp_file_set_mime_type (file, GP_MIME_RAW);
+ gp_file_set_name (file, filename);
+ gp_file_adjust_name_for_mime_type (file);
+ gp_file_set_data_and_size (file, frame_data, datasize);
+ return (GP_OK);
+ default:
+ return GP_ERROR_NOT_SUPPORTED;
+ }
+
+ /* Write the frame(s) */
+ snprintf(buf, sizeof(buf),
+ "P6\n"
+ "# CREATOR: gphoto2, iClick library\n"
+ "%d %d\n"
+ "255\n", w, h);
+ hdrsize = strlen(buf);
+
+ ppmsize = (hdrsize + w*h*3) * nb_frames;
+ GP_DEBUG ("ppmsize = %i\n", ppmsize);
+
+ ptr = ppm = malloc(ppmsize);
+
+ unsigned char *frame_ptr = frame_data + 0x100;
+ /* Here, we just threw away the "superfluous" first 0x100 bytes */
+ memcpy(ptr, buf, hdrsize);
+ ptr += hdrsize;
+
+ gp_bayer_decode (frame_ptr, w , h , ptr, BAYER_TILE_GBRG);
+
+ gp_gamma_fill_table (gtable, .5);
+ /* The gamma factor is pure guesswork; shooting in the dark. This
+ * is the kind of thing which might be hidden in those 0x100 bytes.
+ */
+
+ gp_gamma_correct_single (gtable, ptr, w * h);
+
+ ptr += w*h*3;
+
+ gp_file_set_mime_type (file, GP_MIME_PPM);
+ gp_file_set_name (file, filename);
+ gp_file_set_data_and_size (file, ppm, ppmsize);
+
+ free (frame_data);
+
+ return GP_OK;
+}
+
+
+/*************** Exit and Initialization Functions ******************/
+
+static int
+camera_exit (Camera *camera, GPContext *context)
+{
+ GP_DEBUG ("iClick camera_exit");
+
+ if (camera->pl->data_offset != -1)
+ icl_rewind (camera->port, camera->pl);
+ icl_reset (camera->port);
+
+ if (camera->pl) {
+ free (camera->pl->catalog);
+ free (camera->pl);
+ camera->pl = NULL;
+ }
+
+ return GP_OK;
+}
+
+int
+camera_init(Camera *camera, GPContext *context)
+{
+ GPPortSettings settings;
+ int ret = 0;
+
+ /* First, set up all the function pointers */
+ camera->functions->summary = camera_summary;
+ camera->functions->manual = camera_manual;
+ camera->functions->about = camera_about;
+ camera->functions->exit = camera_exit;
+
+ GP_DEBUG ("Initializing the camera\n");
+
+ ret = gp_port_get_settings(camera->port,&settings);
+ if (ret < 0) return ret;
+
+ ret = gp_port_set_settings(camera->port,settings);
+ if (ret < 0) return ret;
+
+ /* Tell the CameraFilesystem where to get lists from */
+ 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_folder_funcs (camera->fs, NULL, NULL,
+ NULL, NULL, camera);
+
+ camera->pl = malloc (sizeof (CameraPrivateLibrary));
+ if (!camera->pl) return GP_ERROR_NO_MEMORY;
+ camera->pl->model = 0;
+ camera->pl->catalog = NULL;
+ camera->pl->nb_entries = 0;
+ camera->pl->data_offset = -1;
+
+ /* Connect to the camera */
+ ret = icl_init (camera->port, camera->pl);
+ if (ret != GP_OK) {
+ free(camera->pl);
+ return ret;
+ };
+
+
+ return GP_OK;
+}