3 * Copyright (C) 2003 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>
35 # define _(String) dgettext (PACKAGE, String)
37 # define N_(String) gettext_noop (String)
39 # define N_(String) (String)
42 # define _(String) (String)
43 # define N_(String) (String)
47 #include <gphoto2/gphoto2-port.h>
49 #define GP_MODULE "aox"
51 struct _CameraPrivateLibrary {
58 CameraDriverStatus status;
59 unsigned short idVendor;
60 unsigned short idProduct;
62 {"Concord EyeQMini_1", GP_DRIVER_STATUS_EXPERIMENTAL, 0x03e8, 0x2182},
63 {"Concord EyeQMini_2", GP_DRIVER_STATUS_EXPERIMENTAL, 0x03e8, 0x2180},
64 {"D-MAX DM3588", GP_DRIVER_STATUS_EXPERIMENTAL, 0x03e8, 0x2130},
69 camera_id (CameraText *id)
71 strcpy (id->text, "Aox chipset camera");
76 camera_abilities (CameraAbilitiesList *list)
81 for (i = 0; models[i].name; i++) {
82 memset (&a, 0, sizeof(a));
83 strcpy (a.model, models[i].name);
84 a.status = models[i].status;
87 a.usb_vendor = models[i].idVendor;
88 a.usb_product= models[i].idProduct;
89 if (a.status == GP_DRIVER_STATUS_EXPERIMENTAL)
90 a.operations = GP_OPERATION_NONE;
92 a.operations = GP_OPERATION_CAPTURE_IMAGE;
93 a.folder_operations = GP_FOLDER_OPERATION_NONE;
94 a.file_operations = GP_FILE_OPERATION_PREVIEW;
95 gp_abilities_list_append (list, a);
101 camera_summary (Camera *camera, CameraText *summary, GPContext *context)
104 int num_lo_pics =aox_get_num_lo_pics(camera->pl->info);
105 int num_hi_pics =aox_get_num_hi_pics(camera->pl->info);
107 sprintf (summary->text,_("Your USB camera has an Aox chipset.\n"
108 "Number of lo-res PICs = %i\n"
109 "Number of hi-res PICs = %i\n"
110 "Number of PICs = %i\n"
111 ), num_lo_pics, num_hi_pics, num_lo_pics+num_hi_pics);
118 camera_about (Camera *camera, CameraText *about, GPContext *context)
120 strcpy (about->text, _("Aox generic driver\n"
121 "Theodore Kilgore <kilgota@auburn.edu>\n"));
125 /*************** File and Downloading Functions *******************/
128 file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
129 void *data, GPContext *context)
131 Camera *camera = data;
132 int num_lo_pics = aox_get_num_lo_pics (camera->pl->info);
133 int num_hi_pics = aox_get_num_hi_pics (camera->pl->info);
134 int n = num_hi_pics + num_lo_pics;
137 /* Low-resolution pictures are always downloaded first. We do not know
138 * yet how to process them, so they will remain in RAW format. */
140 for (i=0; i< num_lo_pics; i++){
141 snprintf( name, sizeof(name), "aox_pic%03i.raw", i+1 );
142 gp_list_append(list, name, NULL);
145 for (i = num_lo_pics; i < n; i++){
146 snprintf( name, sizeof(name), "aox_pic%03i.ppm", i+1 );
147 gp_list_append(list, name, NULL);
153 get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
154 CameraFileType type, CameraFile *file, void *user_data,
157 Camera *camera = user_data;
159 /* The camera will always download the low-resolution pictures first, if any.
160 * As those are compressed, they are not of fixed size. Unfortunately, the
161 * compression method is not known.
162 * For a high-resolution picture, the size is always the same.
163 * Every picture file has a header, which is of length 0x98. The high-
164 * resolution pictures are just Bayer data; their headers will be discarded.
167 int i, j, k, n, num_lo_pics, num_hi_pics, w = 0, h = 0;
170 unsigned char *p_data = NULL;
171 unsigned char *output = NULL;
175 unsigned char gtable[256];
177 k = gp_filesystem_number(camera->fs, "/", filename, context);
180 num_lo_pics = aox_get_num_lo_pics(camera->pl->info);
181 num_hi_pics = aox_get_num_hi_pics(camera->pl->info);
184 GP_DEBUG("There are %i compressed photos\n", num_lo_pics);
185 GP_DEBUG("There are %i hi-res photos\n", num_hi_pics);
187 if ( (k < num_lo_pics) ) {
197 len = aox_get_picture_size (camera->port, num_lo_pics,
199 GP_DEBUG("len = %i\n", len);
202 printf("Malloc failed\n"); return 0;}
203 aox_read_picture_data (camera->port, (char *)data, len, n);
206 case GP_FILE_TYPE_EXIF:
207 return (GP_ERROR_FILE_EXISTS);
209 case GP_FILE_TYPE_PREVIEW:
210 case GP_FILE_TYPE_NORMAL:
212 gp_file_detect_mime_type (file); /* Detected as "raw"*/
213 gp_file_set_data_and_size (file, (char *)data, len);
214 gp_file_adjust_name_for_mime_type (file);
217 /* Stripping useless header */
218 p_data = data + 0x98;
219 /* Picture is mirror-imaged.*/
220 for (i = 0; i < h; ++i) {
221 for (j = 0 ; j < w/2; j++) {
222 temp = p_data[w*i +j];
223 p_data[w*i +j] = p_data[w*i+ w -1 -j];
224 p_data[w*i + w - 1 - j] = temp;
227 /* Not only this, but some columns are
228 * interchanged, too. */
229 for (i = 0; i < w*h/4; i++) {
230 temp = p_data[4*i +1];
231 p_data[4*i + 1] = p_data[4*i+2];
232 p_data[4*i+2] = temp;
234 /* And now create a ppm file, with our own header */
235 header_len = snprintf(header, 127,
237 "# CREATOR: gphoto2, aox library\n"
241 output = malloc(3*w*h);
244 return GP_ERROR_NO_MEMORY;
246 if (camera->pl->model == AOX_MODEL_DMAX)
247 gp_bayer_decode (p_data, w, h,
248 output, BAYER_TILE_RGGB);
250 gp_bayer_decode (p_data, w, h,
251 output, BAYER_TILE_GRBG);
252 /* gamma correction of .70 may not be optimal. */
253 gp_gamma_fill_table (gtable, .65);
254 gp_gamma_correct_single (gtable, output, w * h);
255 gp_file_set_mime_type (file, GP_MIME_PPM);
256 gp_file_append (file, header, header_len);
257 gp_file_append (file, (char *)output, 3*w*h);
261 case GP_FILE_TYPE_RAW:
262 gp_file_set_data_and_size (file, (char *)data, len);
263 gp_file_set_mime_type (file, GP_MIME_RAW);
264 gp_file_adjust_name_for_mime_type(file);
267 return (GP_ERROR_NOT_SUPPORTED);
274 /*************** Exit and Initialization Functions ******************/
277 camera_exit (Camera *camera, GPContext *context)
279 GP_DEBUG ("Aox camera_exit");
289 static CameraFilesystemFuncs fsfuncs = {
290 .file_list_func = file_list_func,
291 .get_file_func = get_file_func
295 camera_init(Camera *camera, GPContext *context)
297 GPPortSettings settings;
298 CameraAbilities abilities;
301 /* First, set up all the function pointers */
302 camera->functions->summary = camera_summary;
303 camera->functions->about = camera_about;
304 camera->functions->exit = camera_exit;
306 GP_DEBUG ("Initializing the camera\n");
307 ret = gp_port_get_settings(camera->port,&settings);
308 if (ret < 0) return ret;
310 ret = gp_camera_get_abilities(camera,&abilities);
311 if (ret < 0) return ret;
312 GP_DEBUG("product number is 0x%x\n", abilities.usb_product);
314 switch (camera->port->type) {
318 settings.usb.config = 1;
319 settings.usb.altsetting = 0;
320 settings.usb.interface = 1;
321 settings.usb.inep = 0x84;
322 settings.usb.outep =0x05;
328 ret = gp_port_set_settings(camera->port,settings);
329 if (ret < 0) return ret;
331 GP_DEBUG("interface = %i\n", settings.usb.interface);
332 GP_DEBUG("inep = %x\n", settings.usb.inep);
333 GP_DEBUG("outep = %x\n", settings.usb.outep);
335 /* Tell the CameraFilesystem where to get lists from */
336 gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
338 camera->pl = malloc (sizeof (CameraPrivateLibrary));
339 if (!camera->pl) return GP_ERROR_NO_MEMORY;
340 memset (camera->pl, 0, sizeof (CameraPrivateLibrary));
342 switch(abilities.usb_product) {
344 camera->pl->model = AOX_MODEL_DMAX;
347 camera->pl->model = AOX_MODEL_MINI;
349 /* Connect to the camera */
350 aox_init (camera->port, &camera->pl->model, camera->pl->info);