1 /****************************************************************/
2 /* gsmart300.c - Gphoto2 library for the Mustek gSmart 300 */
4 /* Copyright (C) 2002 Jérôme Lodewyck */
6 /* Author: Jérôme Lodewyck <jerome.lodewyck@ens.fr> */
8 /* based on code by: Till Adam <till@adam-lilienthal.de> */
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 */
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 */
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 /****************************************************************/
33 #include <gphoto2/gphoto2.h>
34 #include "gphoto2-endian.h"
36 #include "gsmart300.h"
37 #include "gsmart300-jpeg-header.h"
42 # define _(String) dgettext (PACKAGE, String)
44 # define N_(String) gettext_noop (String)
46 # define N_(String) (String)
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)
58 #define GP_MODULE "gsmart300"
59 static int gsmart300_download_data (CameraPrivateLibrary * lib,
60 int data_type, uint16_t index, unsigned int size,
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,
66 struct GsmartFile *g_file);
69 #define __GS300_THUMB 1
71 #define __GS300_INIT 3
74 gsmart300_get_file_count (CameraPrivateLibrary * lib)
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));
85 gsmart300_delete_file (CameraPrivateLibrary * lib, unsigned int index)
87 struct GsmartFile *g_file;
90 CHECK (gsmart300_get_file_info (lib, index, &g_file));
92 fat_index = 0x1FFF - index;
94 CHECK (gp_port_usb_msg_write (lib->gpdev, 0x03, fat_index, 0x0003,
98 /* Reread fats the next time it is accessed */
104 /* GSmart 300 specific */
106 gsmart300_delete_all (CameraPrivateLibrary * lib)
108 CHECK (gp_port_usb_msg_write (lib->gpdev, 0x02, 0x0000, 0x0004,
112 /* Reread fats the next time it is accessed */
119 gsmart300_request_file (CameraPrivateLibrary * lib, CameraFile *file,
122 struct GsmartFile *g_file;
123 uint8_t *p, *lp_jpg, *start_of_file;
124 uint8_t qIndex, value;
127 /* NOTE : these varialbes are slightly renamed */
128 int flash_size, data_size, file_size;
130 CHECK (gsmart300_get_file_info (lib, number, &g_file));
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
139 qIndex = p[7] & 0x07;
141 file_size = data_size + GSMART_JPG_DEFAULT_HEADER_LENGTH + 1024 * 10;
143 /* slurp in the image */
144 mybuf = malloc (flash_size);
146 return GP_ERROR_NO_MEMORY;
148 ret = gsmart300_download_data (lib, __GS300_PIC, g_file->index,
155 /* now build a jpeg */
156 lp_jpg = malloc (file_size);
159 return GP_ERROR_NO_MEMORY;
161 start_of_file = lp_jpg;
163 /* copy the header from the template */
164 memcpy (lp_jpg, Gsmart_300_JPGDefaultHeader,
165 GSMART_JPG_DEFAULT_HEADER_LENGTH);
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);
171 /* modify the image width, height */
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 */
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 */
181 /* point to real JPG compress data start position and copy */
182 lp_jpg += GSMART_JPG_DEFAULT_HEADER_LENGTH;
184 for (i = 0; i < data_size; i++) {
185 value = *(mybuf + i) & 0xFF;
193 /* Add end of image marker */
197 gp_file_append (file, (char*)start_of_file, lp_jpg - start_of_file);
198 free (start_of_file);
203 gsmart300_request_thumbnail (CameraPrivateLibrary * lib, CameraFile *file,
204 unsigned int number, int *type)
206 struct GsmartFile *g_file;
208 CHECK (gsmart300_get_file_info (lib, number, &g_file));
210 *type = g_file->mime_type;
211 return (gsmart300_get_image_thumbnail (lib, file, g_file));
217 gsmart300_get_image_thumbnail (CameraPrivateLibrary * lib, CameraFile *file,
218 struct GsmartFile *g_file)
221 uint8_t *mybuf = NULL;
223 unsigned int t_width, t_height;
224 uint8_t *yuv_p, *rgb_p;
230 /* No thumbnail for 320x240 pictures */
231 if (g_file->width < 640)
232 return (GP_ERROR_NOT_SUPPORTED);
236 snprintf (pbm_header, sizeof (pbm_header), "P6 %d %d 255\n",
239 /* size needed for download */
242 mybuf = malloc (size);
244 return (GP_ERROR_NO_MEMORY);
245 ret = gsmart300_download_data (lib, __GS300_THUMB, g_file->index,
251 /* effective size of file */
254 len = t_width * t_height * 3;
258 return (GP_ERROR_NO_MEMORY);
261 gp_file_append (file, pbm_header, strlen(pbm_header));
266 while (yuv_p < mybuf + size) {
267 unsigned int u, v, y, y2;
268 unsigned int r, g, b;
275 CHECK (yuv2rgb (y, u, v, &r, &g, &b));
280 CHECK (yuv2rgb (y2, u, v, &r, &g, &b));
288 gp_file_append (file, (char*)buf, len);
294 gsmart300_get_info (CameraPrivateLibrary * lib)
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));
308 gsmart300_get_file_info (CameraPrivateLibrary * lib, unsigned int index,
309 struct GsmartFile **g_file)
312 CHECK (gsmart300_get_info (lib));
313 *g_file = &(lib->files[index]);
318 gsmart300_reset (CameraPrivateLibrary * lib)
320 GP_DEBUG ("* gsmart300_reset");
321 CHECK (gp_port_usb_msg_write (lib->gpdev, 0x02, 0x0000, 0x0003,
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)
334 uint16_t fat_index = 0x1fff - index;
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,
349 CHECK (gp_port_usb_msg_write (lib->gpdev, 0x0a, 0x00,
353 for (i = 0; i < size >> 8; i++)
354 CHECK (gp_port_read (lib->gpdev, (char*)(buf + i*0x100), 0x100));
360 gsmart300_get_FATs (CameraPrivateLibrary * lib)
363 unsigned int index = 0;
364 unsigned int file_index = 0;
368 CHECK (gsmart300_get_file_count(lib));
372 lib->fats = malloc ((lib->num_files) * FLASH_PAGE_SIZE_300);
376 lib->files = malloc (lib->num_files * sizeof (struct GsmartFile));
380 while (index < lib->num_files) {
381 CHECK (gsmart300_download_data (lib, __GS300_FAT, index,
382 FLASH_PAGE_SIZE_300, p));
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);
398 p += FLASH_PAGE_SIZE_300;
406 yuv2rgb (int y, int u, int v, unsigned int *_r, unsigned int *_g, unsigned int *_b)
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;