3 * Copyright (C) 2006 Theodore Kilgore <kilgota@auburn.edu>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
30 #include <gphoto2/gphoto2.h>
37 # define _(String) dgettext (PACKAGE, String)
39 # define N_(String) gettext_noop (String)
41 # define N_(String) (String)
44 # define _(String) (String)
45 # define N_(String) (String)
49 #include <gphoto2/gphoto2-port.h>
51 #define GP_MODULE "jl2005a"
55 CameraDriverStatus status;
56 unsigned short idVendor;
57 unsigned short idProduct;
59 {"American Idol Keychain Camera", GP_DRIVER_STATUS_TESTING,
61 {"NogaNet TDC-15", GP_DRIVER_STATUS_TESTING, 0x0979, 0x0224},
62 {"Cobra DC125", GP_DRIVER_STATUS_EXPERIMENTAL, 0x0979, 0x0224},
67 camera_id (CameraText *id)
69 strcpy (id->text, "JL2005A camera");
74 camera_abilities (CameraAbilitiesList *list)
79 for (i = 0; models[i].name; i++) {
80 memset (&a, 0, sizeof(a));
81 strcpy (a.model, models[i].name);
82 a.status = models[i].status;
85 a.usb_vendor = models[i].idVendor;
86 a.usb_product= models[i].idProduct;
87 if (a.status == GP_DRIVER_STATUS_EXPERIMENTAL)
88 a.operations = GP_OPERATION_NONE;
90 a.operations = GP_OPERATION_CAPTURE_IMAGE;
91 a.folder_operations = GP_FOLDER_OPERATION_NONE;
92 a.file_operations = GP_FILE_OPERATION_PREVIEW
93 + GP_FILE_OPERATION_RAW;
94 gp_abilities_list_append (list, a);
100 camera_summary (Camera *camera, CameraText *summary, GPContext *context)
103 num_pics = camera->pl->nb_entries;
104 GP_DEBUG("camera->pl->nb_entries = %i\n",camera->pl->nb_entries);
105 sprintf (summary->text,_("This camera contains a Jeilin JL2005A chipset.\n"
106 "The number of photos in it is %i. \n"), num_pics);
111 static int camera_manual (Camera *camera, CameraText *manual, GPContext *context)
115 "This driver supports cameras with Jeilin jl2005a chip \n"
116 "These cameras do not support deletion of photos, nor uploading\n"
118 "Decoding of compressed photos may or may not work well\n"
119 "and does not work equally well for all supported cameras.\n"
120 "If present on the camera, video clip frames are downloaded \n"
121 "as consecutive still photos.\n"
122 "For further details please consult libgphoto2/camlibs/README.jl2005a\n"
130 camera_about (Camera *camera, CameraText *about, GPContext *context)
132 strcpy (about->text, _("jl2005a camera library\n"
133 "Theodore Kilgore <kilgota@auburn.edu>\n"));
137 /*************** File and Downloading Functions *******************/
140 file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
141 void *data, GPContext *context)
143 Camera *camera = data;
145 n = camera->pl->nb_entries;
146 gp_list_populate (list, "jl_%03i.ppm", n);
151 get_info_func (CameraFilesystem *fs, const char *folder, const char *filename,
152 CameraFileInfo *info, void *data, GPContext *context)
154 info->file.fields = GP_FILE_INFO_TYPE;
155 strcpy (info->file.type, GP_MIME_PPM);
161 get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
162 CameraFileType type, CameraFile *file, void *user_data,
165 Camera *camera = user_data;
171 unsigned char header[5] = "\xff\xff\xff\xff\x55";
174 unsigned char *image_start;
175 unsigned char *p_data=NULL;
176 unsigned char *ppm=NULL, *ptr=NULL;
177 unsigned char gtable[256];
180 GP_DEBUG ("Downloading pictures!\n");
182 /* These are cheap cameras. There ain't no EXIF data. So kill this. */
183 if (GP_FILE_TYPE_EXIF == type) return GP_ERROR_FILE_EXISTS;
184 /* Get the number of the photo on the camera */
185 k = gp_filesystem_number (camera->fs, "/", filename, context);
186 GP_DEBUG ("Filesystem number is %i\n",k);
187 b = jl2005a_get_pic_data_size(camera->port, k);
188 GP_DEBUG("b = %i = 0x%x bytes\n", b,b);
189 w = jl2005a_get_pic_width(camera->port);
190 GP_DEBUG ("width is %i\n", w);
191 h = jl2005a_get_pic_height(camera->port);
192 GP_DEBUG ("height is %i\n", h);
193 /* Image data to be downloaded contains header and footer bytes */
194 data = malloc (b+14);
195 if (!data) return GP_ERROR_NO_MEMORY;
197 jl2005a_read_picture_data (camera, camera->port, data, b+14);
198 if (memcmp(header,data,5) != 0)
199 /* Image data is corrupted! Repeat the operation. */
200 jl2005a_read_picture_data (camera, camera->port, data, b+14);
202 if (GP_FILE_TYPE_RAW == type) {
203 gp_file_set_mime_type(file, GP_MIME_RAW);
204 gp_file_set_name(file, filename);
205 gp_file_set_data_and_size(file, (char *)data , b+14 );
209 /* Now get ready to put the data into a PPM image file. */
210 p_data = malloc( w*h );
212 status = GP_ERROR_NO_MEMORY;
217 for (i=1; i < h; i +=4){
218 for (j=1; j< w; j ++){
219 temp=image_start[i*w+j];
220 image_start[i*w+j] = image_start[(i+1)*w+j];
221 image_start[(i+1)*w+j] = temp;
233 p_data = malloc( w*h );
235 status = GP_ERROR_NO_MEMORY;
239 jl2005a_decompress (image_start, p_data, w, h);
241 memcpy(p_data, image_start, w*h);
242 ppm = malloc (w * h * 3 + 256); /* room for data and header */
244 status = GP_ERROR_NO_MEMORY;
247 sprintf ((char *)ppm,
249 "# CREATOR: gphoto2, JL2005A library\n"
252 size = strlen ((char *)ppm);
254 size = size + (w * h * 3);
255 GP_DEBUG ("size = %i\n", size);
256 gp_ahd_decode (p_data, w , h, ptr, BAYER_TILE_BGGR);
259 gp_gamma_fill_table (gtable, .65);
260 gp_gamma_correct_single (gtable, ptr, w * h);
261 gp_file_set_mime_type (file, GP_MIME_PPM);
262 gp_file_set_name (file, filename);
263 gp_file_set_data_and_size (file, (char *)ppm, size);
277 /*************** Exit and Initialization Functions ******************/
280 camera_exit (Camera *camera, GPContext *context)
282 GP_DEBUG ("jl2005a camera_exit");
283 jl2005a_reset(camera, camera->port);
284 gp_port_close(camera->port);
292 static CameraFilesystemFuncs fsfuncs = {
293 .file_list_func = file_list_func,
294 .get_file_func = get_file_func,
295 .get_info_func = get_info_func
299 camera_init(Camera *camera, GPContext *context)
301 GPPortSettings settings;
304 /* First, set up all the function pointers */
305 camera->functions->manual = camera_manual;
306 camera->functions->summary = camera_summary;
307 camera->functions->about = camera_about;
308 camera->functions->exit = camera_exit;
310 GP_DEBUG ("Initializing the camera\n");
311 ret = gp_port_get_settings(camera->port,&settings);
312 if (ret < 0) return ret;
314 switch (camera->port->type) {
318 settings.usb.config = 1;
319 settings.usb.altsetting = 0;
320 settings.usb.interface = 0;
321 /* inep 0x84 used for commands, 0x81 for data. */
322 settings.usb.inep = 0x84;
323 settings.usb.outep = 0x03;
329 ret = gp_port_set_settings(camera->port,settings);
330 if (ret < 0) return ret;
332 GP_DEBUG("interface = %i\n", settings.usb.interface);
333 GP_DEBUG("inep = %x\n", settings.usb.inep);
334 GP_DEBUG("outep = %x\n", settings.usb.outep);
336 /* Tell the CameraFilesystem where to get lists from */
337 gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
339 camera->pl = malloc (sizeof (CameraPrivateLibrary));
340 if (!camera->pl) return GP_ERROR_NO_MEMORY;
341 memset (camera->pl, 0, sizeof (CameraPrivateLibrary));
342 /* Connect to the camera */
343 camera->pl->data_reg_accessed = 0;
344 camera->pl->data_to_read = 0;
345 camera->pl->data_used_from_block = 0;
346 camera->pl->data_cache = NULL;
347 jl2005a_init (camera,camera->port, camera->pl);