Remove generated files
[framework/connectivity/libgphoto2.git] / camlibs / gsmart300 / gsmart300.c
1 /****************************************************************/
2 /* gsmart300.c - Gphoto2 library for the Mustek gSmart 300      */
3 /*                                                              */
4 /* Copyright (C) 2002 Jérôme Lodewyck                           */
5 /*                                                              */
6 /* Author: Jérôme Lodewyck <jerome.lodewyck@ens.fr>             */
7 /*                                                              */
8 /* based on code by: Till Adam <till@adam-lilienthal.de>        */
9 /*                                                              */
10 /* This library is free software; you can redistribute it       */
11 /* and/or modify it under the terms of the GNU Library General  */
12 /* Public License as published by the Free Software Foundation; */
13 /* either version 2 of the License, or (at your option) any     */
14 /* later version.                                               */
15 /*                                                              */
16 /* This library is distributed in the hope that it will be      */
17 /* useful, but WITHOUT ANY WARRANTY; without even the implied   */
18 /* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      */
19 /* PURPOSE.  See the GNU Library General Public License for     */
20 /* more details.                                                */
21 /*                                                              */
22 /* You should have received a copy of the GNU Library General   */
23 /* Public License along with this library; if not, write to the */
24 /* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */
25 /* Boston, MA 02111-1307, USA.                                  */
26 /****************************************************************/
27
28 #include <config.h>
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <gphoto2/gphoto2.h>
34 #include "gphoto2-endian.h"
35
36 #include "gsmart300.h"
37 #include "gsmart300-jpeg-header.h"
38
39 #ifdef ENABLE_NLS
40 #  include <libintl.h>
41 #  undef _
42 #  define _(String) dgettext (PACKAGE, String)
43 #  ifdef gettext_noop
44 #    define N_(String) gettext_noop (String)
45 #  else
46 #    define N_(String) (String)
47 #  endif
48 #else
49 #  define textdomain(String) (String)
50 #  define gettext(String) (String)
51 #  define dgettext(Domain,Message) (Message)
52 #  define dcgettext(Domain,Message,Type) (Message)
53 #  define bindtextdomain(Domain,Directory) (Domain)
54 #  define _(String) (String)
55 #  define N_(String) (String)
56 #endif
57
58 #define GP_MODULE "gsmart300"
59 static int gsmart300_download_data (CameraPrivateLibrary * lib,
60                 int data_type, uint16_t index, unsigned int size,
61                 uint8_t * buf);
62 static int gsmart300_get_FATs (CameraPrivateLibrary * lib);
63 static int yuv2rgb (int y, int u, int v, unsigned int *r, unsigned int *g, unsigned int *b);
64 static int gsmart300_get_image_thumbnail (CameraPrivateLibrary * lib,
65                                        CameraFile *file,
66                                        struct GsmartFile *g_file);
67
68 #define __GS300_FAT             0
69 #define __GS300_THUMB           1
70 #define __GS300_PIC             2
71 #define __GS300_INIT            3
72
73 static int
74 gsmart300_get_file_count (CameraPrivateLibrary * lib)
75 {
76         uint8_t buf[0x100];
77
78         gsmart300_download_data (lib, __GS300_INIT,  0, 0x100, buf);
79         lib->num_files = (buf[21] >> 4) * 10 + (buf[21] & 0xf)
80                         + 100 * ((buf[22] >> 4) * 10 + (buf[22] & 0xf));
81         return (GP_OK);
82 }
83
84 int
85 gsmart300_delete_file (CameraPrivateLibrary * lib, unsigned int index)
86 {
87         struct GsmartFile *g_file;
88         uint16_t fat_index;
89
90         CHECK (gsmart300_get_file_info (lib, index, &g_file));
91
92         fat_index = 0x1FFF - index;
93
94         CHECK (gp_port_usb_msg_write (lib->gpdev, 0x03, fat_index, 0x0003,
95                                       NULL, 0));
96         sleep (1);
97
98         /* Reread fats the next time it is accessed */
99         lib->dirty = 1;
100
101         return GP_OK;
102 }
103
104 /* GSmart 300 specific */
105 int
106 gsmart300_delete_all (CameraPrivateLibrary * lib)
107 {
108         CHECK (gp_port_usb_msg_write (lib->gpdev, 0x02, 0x0000, 0x0004,
109                                       NULL, 0));
110         sleep (3);
111
112         /* Reread fats the next time it is accessed */
113         lib->dirty = 1;
114
115         return GP_OK;
116 }
117
118 int
119 gsmart300_request_file (CameraPrivateLibrary * lib, CameraFile *file,
120                      unsigned int number)
121 {
122         struct GsmartFile *g_file;
123         uint8_t *p, *lp_jpg, *start_of_file;
124         uint8_t qIndex, value;
125         uint8_t *mybuf;
126         int i, ret;
127         /* NOTE : these varialbes are slightly renamed */
128         int flash_size, data_size, file_size;
129
130         CHECK (gsmart300_get_file_info (lib, number, &g_file));
131
132         p = g_file->fat;
133
134         /* decode the image size */
135         flash_size = (p[6] * 0x100 + p[5])*0x200;
136         data_size = (p[13] & 0xff) * 0x10000
137                   + (p[12] & 0xff) * 0x100
138                   + (p[11] & 0xff);
139         qIndex = p[7] & 0x07;
140
141         file_size = data_size + GSMART_JPG_DEFAULT_HEADER_LENGTH + 1024 * 10;
142
143         /* slurp in the image */
144         mybuf = malloc (flash_size);
145         if (!mybuf)
146                 return GP_ERROR_NO_MEMORY;
147
148         ret = gsmart300_download_data (lib, __GS300_PIC, g_file->index,
149                                         flash_size, mybuf);
150         if (ret < GP_OK) {
151                 free (mybuf);
152                 return ret;
153         }
154
155         /* now build a jpeg */
156         lp_jpg = malloc (file_size);
157         if (!lp_jpg) {
158                 free (mybuf);
159                 return GP_ERROR_NO_MEMORY;
160         }
161         start_of_file = lp_jpg;
162
163         /* copy the header from the template */
164         memcpy (lp_jpg, Gsmart_300_JPGDefaultHeader,
165                         GSMART_JPG_DEFAULT_HEADER_LENGTH);
166
167         /* modify quantization table */
168         memcpy (lp_jpg + 7, Gsmart_300_QTable[qIndex * 2], 64);
169         memcpy (lp_jpg + 72, Gsmart_300_QTable[qIndex * 2 + 1], 64);
170
171         /* modify the image width, height */
172
173         /* NOTE : the picture width and height written on flash is either
174          * 640x480 or 320x240, but the real size id 640x480 for ALL pictures */
175
176         *(lp_jpg + 564) = (640) & 0xFF;      /* Image width low byte */
177         *(lp_jpg + 563) = (640 >> 8) & 0xFF; /* Image width high byte */
178         *(lp_jpg + 562) = (480) & 0xFF;      /* Image height low byte */
179         *(lp_jpg + 561) = (480 >> 8) & 0xFF; /* Image height high byte */
180
181         /* point to real JPG compress data start position and copy */
182         lp_jpg += GSMART_JPG_DEFAULT_HEADER_LENGTH;
183
184         for (i = 0; i < data_size; i++) {
185                 value = *(mybuf + i) & 0xFF;
186                 *(lp_jpg) = value;
187                 lp_jpg++;
188                 if (value == 0xFF) {
189                         *(lp_jpg) = 0x00;
190                         lp_jpg++;
191                 }
192         }
193         /* Add end of image marker */
194         *(lp_jpg++) = 0xFF;
195         *(lp_jpg++) = 0xD9;
196         free (mybuf);
197         gp_file_append (file, (char*)start_of_file, lp_jpg - start_of_file);
198         free (start_of_file);
199         return (GP_OK);
200 }
201
202 int
203 gsmart300_request_thumbnail (CameraPrivateLibrary * lib, CameraFile *file,
204                           unsigned int number, int *type)
205 {
206         struct GsmartFile *g_file;
207
208         CHECK (gsmart300_get_file_info (lib, number, &g_file));
209
210         *type = g_file->mime_type;
211         return (gsmart300_get_image_thumbnail (lib, file, g_file));
212 }
213
214
215
216 static int
217 gsmart300_get_image_thumbnail (CameraPrivateLibrary * lib, CameraFile *file,
218                             struct GsmartFile *g_file)
219 {
220         unsigned int size;
221         uint8_t *mybuf = NULL;
222         uint8_t *tmp, *buf;
223         unsigned int t_width, t_height;
224         uint8_t *yuv_p, *rgb_p;
225         uint32_t len;
226         char pbm_header[14];
227         int ret;
228
229
230         /* No thumbnail for 320x240 pictures */
231         if (g_file->width < 640)
232                 return (GP_ERROR_NOT_SUPPORTED);
233
234         t_width = 80;
235         t_height = 60;
236         snprintf (pbm_header, sizeof (pbm_header), "P6 %d %d 255\n",
237                   t_width, t_height);
238
239         /* size needed for download */
240         size = 9728;
241
242         mybuf = malloc (size);
243         if (!mybuf)
244                 return (GP_ERROR_NO_MEMORY);
245         ret = gsmart300_download_data (lib, __GS300_THUMB, g_file->index,
246                                         size, mybuf);
247         if (ret < GP_OK) {
248                 free (mybuf);
249                 return ret;
250         }
251         /* effective size of file */
252         size = 9600;
253
254         len = t_width * t_height * 3;
255         buf = malloc (len);
256         if (!buf) {
257                 free (mybuf);
258                 return (GP_ERROR_NO_MEMORY);
259         }
260
261         gp_file_append (file, pbm_header, strlen(pbm_header));
262
263         tmp = buf;
264         yuv_p = mybuf;
265         rgb_p = tmp;
266         while (yuv_p < mybuf + size) {
267                 unsigned int u, v, y, y2;
268                 unsigned int r, g, b;
269
270                 y = yuv_p[0];
271                 y2 = yuv_p[1];
272                 u = yuv_p[2];
273                 v = yuv_p[3];
274
275                 CHECK (yuv2rgb (y, u, v, &r, &g, &b));
276                 *rgb_p++ = r;
277                 *rgb_p++ = g;
278                 *rgb_p++ = b;
279
280                 CHECK (yuv2rgb (y2, u, v, &r, &g, &b));
281                 *rgb_p++ = r;
282                 *rgb_p++ = g;
283                 *rgb_p++ = b;
284
285                 yuv_p += 4;
286         }
287         free (mybuf);
288         gp_file_append (file, (char*)buf, len);
289         free (buf);
290         return (GP_OK);
291 }
292
293 int
294 gsmart300_get_info (CameraPrivateLibrary * lib)
295 {
296         GP_DEBUG ("* gsmart300_get_info");
297         CHECK (gsmart300_get_file_count (lib));
298         if (lib->num_files > 0) {
299                 CHECK (gsmart300_get_FATs (lib));
300         }
301
302         lib->dirty = 0;
303
304         return GP_OK;
305 }
306
307 int
308 gsmart300_get_file_info (CameraPrivateLibrary * lib, unsigned int index,
309                       struct GsmartFile **g_file)
310 {
311         if (lib->dirty)
312                 CHECK (gsmart300_get_info (lib));
313         *g_file = &(lib->files[index]);
314         return GP_OK;
315 }
316
317 int
318 gsmart300_reset (CameraPrivateLibrary * lib)
319 {
320         GP_DEBUG ("* gsmart300_reset");
321         CHECK (gp_port_usb_msg_write (lib->gpdev, 0x02, 0x0000, 0x0003,
322                                       NULL, 0));
323         sleep (1.5);
324         return GP_OK;
325 }
326
327
328 /* Download procedure for GSmart300 */
329 /* buf must be of length n*0x200 */
330 /* Pictured are pointed by there index which runs over 0 to npic -1*/
331 static int gsmart300_download_data (CameraPrivateLibrary * lib, int data_type,
332                                  uint16_t index, unsigned int size, uint8_t * buf)
333 {
334         uint16_t fat_index = 0x1fff - index;
335         int i;
336
337         if (data_type == __GS300_FAT)
338                 CHECK (gp_port_usb_msg_write (lib->gpdev, 0x03,
339                                               fat_index, 0x0000, NULL, 0));
340         if (data_type == __GS300_THUMB)
341                 CHECK (gp_port_usb_msg_write (lib->gpdev, 0x0a,
342                                               fat_index, 0x0003, NULL, 0));
343         if (data_type == __GS300_PIC)
344                 CHECK (gp_port_usb_msg_write (lib->gpdev, 0x03,
345                                               fat_index, 0x0008, NULL, 0));
346         if (data_type == __GS300_INIT  ) {
347                 CHECK (gp_port_usb_msg_write (lib->gpdev, 0x02, 0x00,
348                                               0x0007, NULL, 0));
349                 CHECK (gp_port_usb_msg_write (lib->gpdev, 0x0a, 0x00,
350                                               0x0001, NULL, 0));
351         }
352
353         for (i = 0; i < size >> 8; i++)
354                 CHECK (gp_port_read (lib->gpdev, (char*)(buf + i*0x100), 0x100));
355
356         return GP_OK;
357 }
358
359 static int
360 gsmart300_get_FATs (CameraPrivateLibrary * lib)
361 {
362         uint8_t type;
363         unsigned int index = 0;
364         unsigned int file_index = 0;
365         uint8_t *p = NULL;
366         char buf[14];
367
368         CHECK (gsmart300_get_file_count(lib));
369
370         if (lib->fats)
371                 free (lib->fats);
372         lib->fats = malloc ((lib->num_files) * FLASH_PAGE_SIZE_300);
373
374         if (lib->files)
375                 free (lib->files);
376         lib->files = malloc (lib->num_files * sizeof (struct GsmartFile));
377
378         p = lib->fats;
379
380         while (index < lib->num_files) {
381                 CHECK (gsmart300_download_data (lib, __GS300_FAT, index,
382                                                 FLASH_PAGE_SIZE_300, p));
383                 if (p[0] == 0xFF)
384                         break;
385                 type = p[0];
386                 if (type == 0x00) {
387                         snprintf (buf, 13, "Image%03d.jpg", index + 1);
388                         lib->files[file_index].mime_type =
389                                 GSMART_FILE_TYPE_IMAGE;
390                         lib->files[file_index].index = index;
391                         lib->files[file_index].fat = p;
392                         lib->files[file_index].width = (p[8] & 0xFF) * 16;
393                         lib->files[file_index].height = (p[9] & 0xFF) * 16;
394                         lib->files[file_index].name = strdup (buf);
395                         file_index++;
396                 }
397
398                 p += FLASH_PAGE_SIZE_300;
399                 index++;
400         }
401
402         return GP_OK;
403 }
404
405 static int
406 yuv2rgb (int y, int u, int v, unsigned int *_r, unsigned int *_g, unsigned int *_b)
407 {
408         double r, g, b;
409
410         r = (char) y + 128 + 1.402 * (char) v;
411         g = (char) y + 128 - 0.34414 * (char) u - 0.71414 * (char) v;
412         b = (char) y + 128 + 1.772 * (char) u;
413
414         if (r > 255)
415                 r = 255;
416         if (g > 255)
417                 g = 255;
418         if (b > 255)
419                 b = 255;
420         if (r < 0)
421                 r = 0;
422         if (g < 0)
423                 g = 0;
424         if (b < 0)
425                 b = 0;
426
427         *_r = r;
428         *_g = g;
429         *_b = b;
430
431         return GP_OK;
432 }