Remove generated files
[framework/connectivity/libgphoto2.git] / camlibs / digigr8 / library.c
1 /* library.c for libgphoto2/camlibs/digigr8
2  *
3  * Copyright (C) 2005 - 2010 Theodore Kilgore <kilgota@auburn.edu>
4  *
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.
9  *
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. 
14  *
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.
19  */
20
21 #include <config.h>
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26
27 #include <bayer.h>
28 #include <gamma.h>
29
30
31 #include <gphoto2/gphoto2.h>
32
33 #ifdef ENABLE_NLS
34 #  include <libintl.h>
35 #  undef _
36 #  define _(String) dgettext (PACKAGE, String)
37 #  ifdef gettext_noop
38 #    define N_(String) gettext_noop (String)
39 #  else
40 #    define N_(String) (String)
41 #  endif
42 #else
43 #  define _(String) (String)
44 #  define N_(String) (String)
45 #endif
46
47 #include "digigr8.h"
48
49 #include <gphoto2/gphoto2-port.h>
50
51 #define GP_MODULE "digigr8"
52
53 static const struct {
54         char *name;
55         CameraDriverStatus status;
56         unsigned short idVendor;
57         unsigned short idProduct;
58 } models[] = {
59         {"Digigr8",             GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x905c},
60         {"Che-Ez Snap SNAP-U",  GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x905c},
61         {"DC-N130t",            GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x905C},
62         {"Soundstar TDC-35",    GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x905c},
63         {"Nexxtech Mini Digital Camera", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770,
64                                                                         0x905c},
65         {"Vivitar Vivicam35",   GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x905c},
66         {"Praktica Slimpix",    GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x905c},
67         {"ZINA Mini Digital Keychain Camera",   GP_DRIVER_STATUS_EXPERIMENTAL,
68                                                             0x2770, 0x905c},
69         {"Pixie Princess Jelly-Soft",           GP_DRIVER_STATUS_EXPERIMENTAL,
70                                                             0x2770, 0x905c},
71         {"Sakar Micro Digital 2428x",           GP_DRIVER_STATUS_EXPERIMENTAL,
72                                                             0x2770, 0x905c},
73         {"Stop & Shop 87096",           GP_DRIVER_STATUS_EXPERIMENTAL,
74                                                             0x2770, 0x905c},
75         {"Jazz JDC9",           GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x905c},
76         {"Disney pix micro",    GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9050},
77         {"Lego Bionicle",       GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9051},
78         /* from IRC reporter, adam@piggz.co.uk */
79         {"Disney pix micro 2",  GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9052},
80         {"Suprema Digital Keychain Camera",     GP_DRIVER_STATUS_EXPERIMENTAL,
81                                                                 0x2770, 0x913d},
82         {"Sakar 28290 and 28292  Digital Concepts Styleshot",
83                                                 GP_DRIVER_STATUS_EXPERIMENTAL,
84                                                                 0x2770, 0x913d},
85         {"Sakar 23070  Crayola Digital Camera",    GP_DRIVER_STATUS_EXPERIMENTAL,
86                                                                 0x2770, 0x913d},
87         {"Sakar 92045  Spiderman",    GP_DRIVER_STATUS_EXPERIMENTAL,
88                                                                 0x2770, 0x913d},
89         {NULL,0,0,0}
90 };
91
92 int
93 camera_id (CameraText *id)
94 {
95         strncpy (id->text, "SQ905C chipset camera",32);
96         return GP_OK;
97 }
98
99
100 int
101 camera_abilities (CameraAbilitiesList *list)
102 {
103         int i;    
104         CameraAbilities a;
105
106         for (i = 0; models[i].name; i++) {
107                 memset (&a, 0, sizeof(a));
108                 strncpy (a.model, models[i].name,32);
109                 a.status = models[i].status;
110                 a.port   = GP_PORT_USB;
111                 a.speed[0] = 0;
112                 a.usb_vendor = models[i].idVendor;
113                 a.usb_product= models[i].idProduct;
114                 if (a.status == GP_DRIVER_STATUS_EXPERIMENTAL)
115                         a.operations = GP_OPERATION_NONE;
116                 else
117                         a.operations = GP_OPERATION_CAPTURE_PREVIEW;
118                 a.folder_operations = GP_FOLDER_OPERATION_DELETE_ALL;
119                 a.file_operations   = GP_FILE_OPERATION_PREVIEW 
120                                         + GP_FILE_OPERATION_RAW;
121                 gp_abilities_list_append (list, a);
122         }
123         return GP_OK;
124 }
125
126 static int
127 camera_summary (Camera *camera, CameraText *summary, GPContext *context)
128 {
129         if(!camera->pl->init_done)
130                 digi_init (camera->port, camera->pl);
131         snprintf (summary->text, 100,
132                         ("Your USB camera seems to have an SQ905C chipset.\n" 
133                         "The total number of pictures in it is %i\n"), 
134                                 camera->pl->nb_entries);  
135         return GP_OK;
136 }
137
138 static int camera_manual(Camera *camera, CameraText *manual,
139                                                         GPContext *context)
140 {
141         strncpy(manual->text, 
142         _(
143         "For cameras with insides from S&Q Technologies, which have the \n"
144         "USB Vendor ID 0x2770 and Product ID 0x905C, 0x9050, 0x9051,\n"
145         "0x9052, or 0x913D.  Photos are saved in PPM format.\n\n"
146         "Some of these cameras allow software deletion of all photos.\n"
147         "Others do not. No supported camera can do capture-image. All\n"
148         "can do capture-preview (image captured and sent to computer).\n"
149         "If delete-all does work for your camera, then capture-preview will\n"
150         "have the side-effect that it also deletes what is on the camera.\n\n"
151         "File uploading is not supported for these cameras. Also, none of the\n"
152         "supported cameras allow deletion of individual photos by use of a\n"
153         "software command.\n"
154         ), 700);
155         return (GP_OK);
156 }
157
158
159 static int
160 camera_about (Camera *camera, CameraText *about, GPContext *context)
161 {
162         strncpy (about->text, _("sq905C generic driver\n"
163                             "Theodore Kilgore <kilgota@auburn.edu>\n"),64);
164         return GP_OK;
165 }
166
167 /*************** File and Downloading Functions *******************/
168
169
170 static int
171 file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
172                 void *data, GPContext *context)
173 {
174         Camera *camera = data; 
175         int n;
176         if(!camera->pl->init_done)
177                 digi_init (camera->port, camera->pl);
178         GP_DEBUG ("List files in %s\n", folder);
179         n = camera->pl->nb_entries;     
180         gp_list_populate(list, "pict%03i.ppm", n);
181         return GP_OK;
182 }
183
184
185 static int
186 get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
187                CameraFileType type, CameraFile *file, void *user_data,
188                GPContext *context)
189 {
190         int status = GP_OK;
191         Camera *camera = user_data; 
192         int w, h, b; 
193         int k, next;
194         unsigned char comp_ratio;
195         unsigned char lighting;
196         unsigned char *data = NULL;
197         unsigned char *p_data = NULL; 
198         unsigned char *ppm;
199         unsigned char *ptr;
200         unsigned char gtable[256];
201         int size;
202
203         if(!camera->pl->init_done)
204                 digi_init (camera->port, camera->pl);
205
206         /* Get the entry number of the photo on the camera */
207         k = gp_filesystem_number (camera->fs, "/", filename, context); 
208
209         if (GP_FILE_TYPE_EXIF ==type) return GP_ERROR_FILE_EXISTS;
210
211         if (GP_FILE_TYPE_RAW!=type && GP_FILE_TYPE_NORMAL
212                                     !=type && GP_FILE_TYPE_PREVIEW!=type) {
213                 return GP_ERROR_NOT_SUPPORTED;
214         }
215         
216         next = camera->pl->last_fetched_entry +1;
217         while (next < k) {
218                 b = digi_get_data_size (camera->pl, next);
219                 data = malloc(b);
220                 if(!data) return GP_ERROR_NO_MEMORY;
221                 digi_read_picture_data (camera->port, data, b, next);
222                 free(data);
223                 next ++;
224         }
225
226         comp_ratio = digi_get_comp_ratio (camera->pl, k);
227         w = digi_get_picture_width (camera->pl, k);
228         switch (w) {
229         case 176: h = 144; break;
230         case 640: h = 480; break;
231         case 320: h = 240; break;
232         default:  h = 288; break;
233         }
234         lighting = camera->pl->catalog[k*0x10+0x0b];
235         b = digi_get_data_size (camera->pl, k);
236         if (!b) {
237                 GP_DEBUG("Photo number %i deleted?\n",k+1);
238                 camera->pl->last_fetched_entry = k;
239                 return GP_OK;
240         }       
241         data = malloc (w*h);
242         if(!data) return GP_ERROR_NO_MEMORY;
243
244         GP_DEBUG("Fetch entry %i\n", k);
245         digi_read_picture_data (camera->port, data, b, k);
246         camera->pl->last_fetched_entry = k;
247
248         if (GP_FILE_TYPE_RAW == type) { /* type is GP_FILE_TYPE_RAW */
249                 size = b; 
250                 gp_file_set_mime_type (file, GP_MIME_RAW);
251                 gp_file_set_name (file, filename);
252                 gp_file_append(file, (char *)data, size);
253                 /* Save photo's catalog entry as a footer for the raw file */
254                 gp_file_append(file, (char *)camera->pl->catalog + k*0x10, 0x10);
255                 /* Reset camera when done, for more graceful exit. */
256                 if (k +1 == camera->pl->nb_entries) {
257                         digi_rewind (camera->port, camera->pl); 
258                 }
259                 free(data);
260                 return(GP_OK);
261         }
262
263         /*
264          * Now put the data into a PPM image file. 
265          */
266
267         ppm = malloc (w * h * 3 + 256); /* room for data + header */
268         if (!ppm) { 
269                 status = GP_ERROR_NO_MEMORY; 
270                 goto end;
271         }
272         snprintf ((char *)ppm, 64,
273                         "P6\n"
274                         "# CREATOR: gphoto2, SQ905C library\n"
275                         "%d %d\n"
276                         "255\n", w, h);
277         size = strlen ((char *)ppm);
278         ptr = ppm + size;
279         size = size + (w * h * 3);
280         GP_DEBUG ("size = %i\n", size);
281         p_data = malloc( w*h );
282         if (!p_data) {
283                 status =  GP_ERROR_NO_MEMORY;
284                 goto end;
285         }
286         if(comp_ratio) {
287                 digi_decompress (p_data, data, w, h);
288         } else
289                 memcpy(p_data, data, w*h);
290         gp_ahd_decode (p_data, w , h , ptr, BAYER_TILE_BGGR);
291         free(p_data);
292         digi_postprocess (w, h, ptr);
293         if (lighting < 0x40) {
294         GP_DEBUG(
295                 "Low light condition. Using default gamma. \
296                                                 No white balance.\n");
297                 gp_gamma_fill_table (gtable, .65); 
298                 gp_gamma_correct_single(gtable,ptr,w*h);
299         } else
300                 white_balance (ptr, w*h, 1.1);
301         gp_file_set_mime_type (file, GP_MIME_PPM);
302         gp_file_set_name (file, filename); 
303         gp_file_set_data_and_size (file, (char *)ppm, size);
304         /* Reset camera when done, for more graceful exit. */
305         if (k +1 == camera->pl->nb_entries) {
306                 digi_rewind (camera->port, camera->pl);
307         }
308  end:
309         free(data);
310         return status;
311 }
312
313 static int
314 delete_all_func (CameraFilesystem *fs, const char *folder, void *data, 
315                 GPContext *context) 
316 {
317         Camera *camera = data;
318         if(!camera->pl->delete_all)
319                 return GP_ERROR_NOT_SUPPORTED;
320         if(!camera->pl->init_done)
321                 digi_init (camera->port, camera->pl);
322         digi_delete_all (camera->port, camera->pl);
323         return GP_OK;
324 }
325
326 static int
327 camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context)
328
329 {
330         unsigned char get_size[0x50];
331         unsigned char *raw_data; 
332         unsigned char *frame_data; 
333         unsigned char *ppm, *ptr;
334         char lighting;
335         unsigned char gtable[256];
336         char filename[14] = "digi_cap.ppm";
337         int size;
338         int w = 320;
339         int h = 240;
340         int b;
341
342         digi_reset (camera->port);
343         gp_port_usb_msg_write (camera->port, 0x0c, 0x1440, 0x110f, NULL, 0);
344         gp_port_read(camera->port, (char *)get_size, 0x50);
345         GP_DEBUG("get_size[0x40] = 0x%x\n", get_size[0x40]);
346         lighting = get_size[0x48];
347         b = get_size[0x40] | get_size[0x41] << 8 | get_size[0x42] << 16
348                                                 | get_size[0x43]<<24;
349         GP_DEBUG("b = 0x%x\n", b);
350         raw_data = malloc(b);
351         if(!raw_data) { 
352                 free(raw_data); 
353                 return GP_ERROR_NO_MEMORY;
354         }
355         if (!((gp_port_read(camera->port, (char *)raw_data, b)==b))) {
356                 GP_DEBUG("Error in reading data\n");
357                 return GP_ERROR;
358         }
359         frame_data = malloc(w*h);
360         if (!frame_data) {
361                 free(frame_data);
362                 return GP_ERROR_NO_MEMORY;
363         }
364         digi_decompress (frame_data, raw_data, w, h);
365         free(raw_data);
366         /* Now put the data into a PPM image file. */
367         ppm = malloc (w * h * 3 + 256); 
368         if (!ppm)
369                 return GP_ERROR_NO_MEMORY;
370         snprintf ((char *)ppm, 64,
371                 "P6\n"
372                 "# CREATOR: gphoto2, SQ905C library\n"
373                 "%d %d\n"
374                 "255\n", w, h);
375         ptr = ppm + strlen ((char*)ppm);
376         size = strlen ((char*)ppm) + (w * h * 3);
377         GP_DEBUG ("size = %i\n", size);
378         gp_ahd_decode (frame_data, w , h , ptr, BAYER_TILE_BGGR);
379         free(frame_data);
380         if (lighting < 0x40) {
381         GP_DEBUG(
382                 "Low light condition. Default gamma. No white balance.\n");
383                 gp_gamma_fill_table (gtable, .65);
384                 gp_gamma_correct_single(gtable,ptr,w*h);
385         } else
386                 white_balance (ptr, w*h, 1.1);
387         gp_file_set_mime_type (file, GP_MIME_PPM);
388         gp_file_set_name (file, filename);
389         gp_file_set_data_and_size (file, (char *)ppm, size);
390         digi_reset(camera->port);
391         return (GP_OK);
392 }
393
394 /*************** Exit and Initialization Functions ******************/
395
396 static int
397 camera_exit (Camera *camera, GPContext *context)
398 {
399         GP_DEBUG ("SQ camera_exit");
400         digi_reset (camera->port);
401
402         if (camera->pl) {
403                 free (camera->pl->catalog);
404                 free (camera->pl);
405                 camera->pl = NULL;
406         }
407         return GP_OK;
408 }
409
410 static CameraFilesystemFuncs fsfuncs = {
411         .file_list_func = file_list_func,
412         .get_file_func = get_file_func,
413         .delete_all_func = delete_all_func
414 };
415
416 int
417 camera_init(Camera *camera, GPContext *context)
418 {
419         GPPortSettings settings;
420         CameraAbilities abilities;
421         int ret = 0;
422
423         ret = gp_camera_get_abilities(camera,&abilities);
424         if (ret < 0) return ret;        
425         GP_DEBUG("product number is 0x%x\n", abilities.usb_product);
426
427         /* Now, set up all the function pointers */
428         camera->functions->summary      = camera_summary;
429         camera->functions->manual       = camera_manual;
430         camera->functions->about        = camera_about;
431         camera->functions->capture_preview      
432                                         = camera_capture_preview;
433         camera->functions->exit         = camera_exit;
434
435         GP_DEBUG ("Initializing the camera\n");
436
437         ret = gp_port_get_settings(camera->port,&settings);
438         if (ret < 0)
439                 return ret;
440         ret = gp_port_set_settings(camera->port,settings);
441         if (ret < 0)
442                 return ret;
443
444         /* Tell the CameraFilesystem where to get lists from */
445         gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
446         camera->pl = malloc (sizeof (CameraPrivateLibrary));
447         if (!camera->pl) 
448                 return GP_ERROR_NO_MEMORY;
449         camera->pl->catalog = NULL;
450         camera->pl->nb_entries = 0;
451         switch (abilities.usb_product) {
452                 case 0x9050:
453         case 0x9051:
454                 case 0x9052:
455                         camera->pl->delete_all = 1;
456                         break; 
457                 default:
458                         camera->pl->delete_all = 0;
459         }
460         camera->pl->init_done=0;
461
462         /* Do digi_init() only if needed for the requested operation. */
463
464         return GP_OK;
465 }