Remove generated files
[framework/connectivity/libgphoto2.git] / camlibs / spca50x / library.c
1 /****************************************************************/
2 /* library.c - Gphoto2 library for cameras with sunplus spca50x */
3 /*             chips                                            */
4 /* Copyright (C) 2002, 2003 Till Adam                           */
5 /*                                                              */
6 /* Author: Till Adam <till@adam-lilienthal.de>                  */
7 /*                                                              */
8 /* This library is free software; you can redistribute it       */
9 /* and/or modify it under the terms of the GNU Library General  */
10 /* Public License as published by the Free Software Foundation; */
11 /* either version 2 of the License, or (at your option) any     */
12 /* later version.                                               */
13 /*                                                              */
14 /* This library is distributed in the hope that it will be      */
15 /* useful, but WITHOUT ANY WARRANTY; without even the implied   */
16 /* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      */
17 /* PURPOSE.  See the GNU Library General Public License for     */
18 /* more details.                                                */
19 /*                                                              */
20 /* You should have received a copy of the GNU Library General   */
21 /* Public License along with this library; if not, write to the */
22 /* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */
23 /* Boston, MA 02111-1307, USA.                                  */
24 /****************************************************************/
25
26 #include "config.h"
27
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include <gphoto2/gphoto2.h>
34 #include <gphoto2/gphoto2-port.h>
35
36 #ifdef ENABLE_NLS
37 #  include <libintl.h>
38 #  undef _
39 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
40 #  ifdef gettext_noop
41 #    define N_(String) gettext_noop (String)
42 #  else
43 #    define N_(String) (String)
44 #  endif
45 #else
46 #  define _(String) (String)
47 #  define N_(String) (String)
48 #endif
49
50 #include "spca50x.h"
51 #include "spca50x-flash.h"
52 #include "spca50x-sdram.h"
53
54 #define GP_MODULE "spca50x"
55 #define TIMEOUT       5000
56
57 #define SPCA50X_VERSION "0.1"
58 #define SPCA50X_LAST_MOD "02/09/03 - 23:14:11"
59
60 /* forward declarations */
61 static int file_list_func (CameraFilesystem *fs, const char *folder,
62                            CameraList *list, void *data, GPContext *context);
63 static int get_file_func (CameraFilesystem *fs, const char *folder,
64                           const char *filename, CameraFileType type,
65                           CameraFile *file, void *user_data,
66                           GPContext *context);
67
68 static int delete_file_func (CameraFilesystem *fs, const char *folder,
69                              const char *filename, void *data,
70                              GPContext *context);
71 static int delete_all_func (CameraFilesystem *fs, const char *folder,
72                             void *data, GPContext *context);
73 static int get_info_func (CameraFilesystem *fs, const char *folder,
74                           const char *filename, CameraFileInfo *info,
75                           void *data, GPContext *context);
76 static int cam_has_sdram (CameraPrivateLibrary *pl);
77 static int cam_has_flash (CameraPrivateLibrary *pl);
78 static int cam_has_card (CameraPrivateLibrary *pl);
79
80 /* define what cameras we support */
81 static const struct
82 {
83         char *model;
84         int usb_vendor;
85         int usb_product;
86         SPCA50xBridgeChip bridge;
87         int storage_media_mask;
88 }
89 models[] =
90 {
91         /* firmware version 1 cams. */
92         {"Mustek:gSmart mini", 0x055f, 0xc220,
93                 BRIDGE_SPCA500, SPCA50X_SDRAM },
94         {"Mustek:gSmart mini 2", 0x055f, 0xc420,
95                 BRIDGE_SPCA504, SPCA50X_SDRAM },
96         {"Mustek:gSmart mini 3", 0x055f, 0xc520,
97                 BRIDGE_SPCA504, SPCA50X_SDRAM },
98         {"So.:Show 301", 0x0ec7, 0x1008,
99                 BRIDGE_SPCA504, SPCA50X_SDRAM },
100         {"Aiptek:Pencam", 0x04fc, 0x504a,
101                 BRIDGE_SPCA504, SPCA50X_SDRAM | SPCA50X_FLASH },
102         /* same ids, different cam *sigh* */
103         {"Aiptek:Pencam without flash", 0x04fc, 0x504a,
104                 BRIDGE_SPCA504, SPCA50X_SDRAM },
105         {"Medion:MD 5319", 0x04fc, 0x504a,
106                 BRIDGE_SPCA504, SPCA50X_SDRAM | SPCA50X_FLASH },
107         {"nisis:Quickpix Qp3", 0x04fc, 0x504a,
108                 BRIDGE_SPCA504, SPCA50X_SDRAM | SPCA50X_FLASH },
109         {"Trust:Spyc@m 500F FLASH", 0x04fc, 0x504a,
110                 BRIDGE_SPCA504, SPCA50X_SDRAM | SPCA50X_FLASH },
111         /* The firmware 2 cams. Those can autodetect their storage type */
112         {"Aiptek:1.3 mega PocketCam", 0x04fc, 0x504b,
113                 BRIDGE_SPCA504, 0 },
114         {"Maxell:Max Pocket", 0x04fc, 0x504b,
115                 BRIDGE_SPCA504, 0 },
116         {"Aiptek:Smart Megacam", 0x04fc, 0x504b,
117                 BRIDGE_SPCA504, 0 },
118         {"Benq:DC1300", 0x04a5, 0x3003,
119                 BRIDGE_SPCA504, 0 },
120         /* Some other 500a cams with flash */
121         {"Trust:Familycam 300", 0x084d, 0x0003,
122                 BRIDGE_SPCA500, SPCA50X_FLASH},
123         {"D-Link:DSC 350+", 0x084d, 0x0003,
124                 BRIDGE_SPCA500, SPCA50X_FLASH},
125         {"Minton:S-Cam F5", 0x084d, 0x0003,
126                 BRIDGE_SPCA500, SPCA50X_FLASH}, 
127         {"PureDigital:Ritz Disposable", 0x04fc, 0xffff,
128                 BRIDGE_SPCA504B_PD, SPCA50X_FLASH},
129         {NULL, 0, 0, 0, 0}
130 };
131
132 int
133 camera_id (CameraText *id)
134 {
135         strcpy (id->text, "spca50x");
136         return (GP_OK);
137 }
138
139 int
140 camera_abilities (CameraAbilitiesList *list)
141 {
142         int x = 0;
143         char *ptr;
144         CameraAbilities a;
145
146         ptr = models[x].model;
147         while (ptr) {
148                 memset (&a, 0, sizeof (a));
149                 strcpy (a.model, ptr);
150                 a.port = GP_PORT_USB;
151                 a.speed[0] = 0;
152                 a.status = GP_DRIVER_STATUS_TESTING;
153
154                 a.file_operations = GP_FILE_OPERATION_PREVIEW
155                                   | GP_FILE_OPERATION_DELETE;
156
157                 a.folder_operations = GP_FOLDER_OPERATION_DELETE_ALL;
158
159                 a.usb_vendor = models[x].usb_vendor;
160                 a.usb_product = models[x].usb_product;
161
162                 if (models[x].bridge == BRIDGE_SPCA504) {
163                         /* FIXME which cams can do it? */
164                         if (a.usb_product == 0xc420
165                          || a.usb_product == 0xc520)
166                                 a.operations = GP_OPERATION_CAPTURE_IMAGE;
167                 }
168                 if (models[x].bridge == BRIDGE_SPCA504B_PD) {
169                             a.operations = GP_OPERATION_CAPTURE_IMAGE;
170                 }
171                 if (models[x].bridge == BRIDGE_SPCA500) {
172                         /* TEST enable capture for the DSC-350 style cams */
173                         if (a.usb_vendor == 0x084d) {
174                                 a.operations = GP_OPERATION_CAPTURE_IMAGE;
175                         }
176                 }
177                 gp_abilities_list_append (list, a);
178
179                 ptr = models[++x].model;
180         }
181
182         return (GP_OK);
183 }
184
185 static int
186 camera_capture (Camera *camera, CameraCaptureType type,
187                 CameraFilePath * path, GPContext *context)
188 {
189         struct SPCA50xFile *file;
190         CameraAbilities a;
191
192         /* Not all our cameras support capture */
193         gp_camera_get_abilities (camera, &a);
194         if (!a.operations & GP_OPERATION_CAPTURE_IMAGE)
195                 return GP_ERROR_NOT_SUPPORTED;
196
197         if (cam_has_flash(camera->pl))
198         {
199                 int fc;
200                 char tmp [14];
201
202                 CHECK(spca500_flash_capture (camera->pl));
203                 CHECK(spca50x_flash_get_TOC (camera->pl, &fc));
204                 /* assume new pic is the last one in the cam...*/
205                 CHECK(spca50x_flash_get_file_name (camera->pl, (fc - 1), tmp));
206
207                 /* Add new image name to file list */
208                 /* NOTE: these lines moved from below */
209                 strncpy (path->name, tmp, sizeof (path->name) - 1);
210                 path->name[sizeof (path->name) - 1] = '\0';
211         }
212         else
213         {
214                 CHECK (spca50x_capture (camera->pl));
215                 CHECK (spca50x_sdram_get_info (camera->pl));
216                 CHECK (spca50x_sdram_get_file_info
217                         (camera->pl, camera->pl->num_files_on_sdram - 1, &file));
218
219                 /* Add new image name to file list */
220                 /* NOTE: these lines moved from below */
221                 strncpy (path->name, file->name, sizeof (path->name) - 1);
222                 path->name[sizeof (path->name) - 1] = '\0';
223         }
224         /* Now tell the frontend where to look for the image */
225         strncpy (path->folder, "/", sizeof (path->folder) - 1);
226         path->folder[sizeof (path->folder) - 1] = '\0';
227
228         CHECK (gp_filesystem_append
229                (camera->fs, path->folder, path->name, context));
230         return GP_OK;
231 }
232
233
234 static int
235 camera_exit (Camera *camera, GPContext *context)
236 {
237         if (camera->pl) {
238                 if (cam_has_flash (camera->pl) || cam_has_card (camera->pl))
239                         spca50x_flash_close (camera->pl, context);
240
241                 if (camera->pl->fats) {
242                         free (camera->pl->fats);
243                         camera->pl->fats = NULL;
244                 }
245                 if (camera->pl->files) {
246                         free (camera->pl->files);
247                         camera->pl->files = NULL;
248                 }
249                 if (camera->pl->flash_toc) {
250                         free (camera->pl->flash_toc);
251                         camera->pl->flash_toc = NULL;
252                 }
253
254                 free (camera->pl);
255                 camera->pl = NULL;
256         }
257         return (GP_OK);
258 }
259
260 static int
261 camera_summary (Camera *camera, CameraText *summary, GPContext *context)
262 {
263         char tmp[1024];
264         int flash_file_count;
265
266         if (cam_has_flash(camera->pl)  || cam_has_card (camera->pl)) {
267                 spca50x_flash_get_filecount(camera->pl, &flash_file_count);
268                 snprintf (tmp, sizeof (tmp),
269                         _("FLASH:\n Files: %d\n"), flash_file_count);
270                 strcat (summary->text, tmp);
271         }
272
273         /* possibly get # pics, mem free, etc. if needed */
274         if (cam_has_sdram(camera->pl) && camera->pl->dirty_sdram) {
275                 CHECK (spca50x_sdram_get_info (camera->pl));
276
277                 snprintf (tmp, sizeof (tmp),
278                                 _("SDRAM:\n Files: %d\n  Images: %4d\n  Movies: %4d\nSpace used: %8d\nSpace free: %8d\n"),
279                                 camera->pl->num_files_on_sdram,
280                                 camera->pl->num_images,
281                                 camera->pl->num_movies,
282                                 camera->pl->size_used,
283                                 camera->pl->size_free);
284                 strcat (summary->text, tmp);
285         }
286
287         return (GP_OK);
288 }
289
290 static int
291 camera_about (Camera *camera, CameraText *about, GPContext *context)
292 {
293         strcpy (about->text,
294                 _("spca50x library v" SPCA50X_VERSION
295                   " " SPCA50X_LAST_MOD "\n"
296                   "Till Adam <till@adam-lilienthal.de>\n"
297                   "Support for digital cameras with a sunplus spca50x chip "
298                   "based on several other gphoto2 camlib modules and "
299                   "the information kindly provided by Mustek.\n"
300                   "\n"));
301
302         return (GP_OK);
303 }
304
305
306
307
308 static int
309 file_list_func (CameraFilesystem *fs, const char *folder,
310                 CameraList *list, void *data, GPContext *context)
311 {
312
313         Camera *camera = data;
314         int i = 0, filecount = 0;
315         char temp_file[14];
316
317         if (cam_has_flash(camera->pl) || cam_has_card(camera->pl) )
318         {
319                 CHECK (spca50x_flash_get_TOC(camera->pl, &filecount));
320                 for (i=0; i<filecount; i++)
321                 {
322                         CHECK(spca50x_flash_get_file_name (camera->pl, i,
323                                                 temp_file));
324                         gp_list_append (list, temp_file, NULL);
325                 }
326         }
327         if (cam_has_sdram(camera->pl)) {
328                 if (camera->pl->dirty_sdram)
329                         CHECK (spca50x_sdram_get_info (camera->pl));
330
331                 for (i = 0; i < camera->pl->num_files_on_sdram; i++) {
332                         strncpy (temp_file, camera->pl->files[i].name, 12);
333                         temp_file[12] = 0;
334                         gp_list_append (list, temp_file, NULL);
335                 }
336         }
337
338         return GP_OK;
339 }
340
341
342 static int
343 get_file_func (CameraFilesystem *fs, const char *folder,
344                const char *filename, CameraFileType type,
345                CameraFile *file, void *user_data, GPContext *context)
346 {
347
348         Camera *camera = user_data;
349         unsigned char *data = NULL;
350         int size, number, filetype, flash_file_count = 0;
351
352         CHECK (number =
353                gp_filesystem_number (camera->fs, folder, filename, context));
354
355         if (cam_has_flash(camera->pl) || cam_has_card(camera->pl) ) {
356                 CHECK (spca50x_flash_get_filecount
357                                         (camera->pl, &flash_file_count));
358         }
359
360         switch (type) {
361                 case GP_FILE_TYPE_NORMAL:
362                         if ( number < flash_file_count) {
363                                 CHECK (spca50x_flash_get_file (camera->pl,
364                                                         context, &data, &size,
365                                                         number, 0));
366                                 CHECK (gp_file_set_mime_type
367                                                 (file, GP_MIME_JPEG));
368
369                         } else {
370                                 CHECK (spca50x_sdram_request_file
371                                                 (camera->pl, &data, &size,
372                                                  number-flash_file_count,
373                                                  &filetype));
374                                 if (filetype == SPCA50X_FILE_TYPE_IMAGE) {
375                                         CHECK (gp_file_set_mime_type
376                                                         (file, GP_MIME_JPEG));
377                                 } else if (filetype == SPCA50X_FILE_TYPE_AVI) {
378                                         CHECK (gp_file_set_mime_type
379                                                         (file, GP_MIME_AVI));
380                                 }
381                         }
382                         break;
383                 case GP_FILE_TYPE_PREVIEW:
384                          if ( number < flash_file_count) {
385                                 CHECK (spca50x_flash_get_file (camera->pl,
386                                                         context, &data, &size,
387                                                         number, 1));
388                                 CHECK (gp_file_set_mime_type (file,
389                                                         GP_MIME_BMP));
390
391                         } else {
392                                 CHECK (spca50x_sdram_request_thumbnail
393                                                 (camera->pl, &data, &size,
394                                                  number-flash_file_count,
395                                                  &filetype));
396                                 if (filetype == SPCA50X_FILE_TYPE_IMAGE) {
397                                         CHECK (gp_file_set_mime_type
398                                                         (file, GP_MIME_BMP));
399                                 } else if (filetype == SPCA50X_FILE_TYPE_AVI) {
400                                         CHECK (gp_file_set_mime_type
401                                                         (file, GP_MIME_JPEG));
402                                 }
403                         }
404
405                         break;
406                 default:
407                         return GP_ERROR_NOT_SUPPORTED;
408         }
409
410         if (!data)
411                 return GP_ERROR;
412
413         CHECK (gp_file_set_data_and_size (file, data, size));
414         CHECK (gp_file_set_name (file, filename));
415
416         return GP_OK;
417 }
418
419 static int
420 get_info_func (CameraFilesystem *fs, const char *folder,
421                const char *filename, CameraFileInfo *info, void *data,
422                GPContext *context)
423 {
424         Camera *camera = data;
425         int n, flash_file_count = 0;
426         struct SPCA50xFile *file;
427         char name[14];
428         int w,h;
429
430         /* Get the file number from the CameraFileSystem */
431         CHECK (n =
432                gp_filesystem_number (camera->fs, folder, filename, context));
433
434         if (cam_has_flash(camera->pl) || cam_has_card(camera->pl) ) {
435                 CHECK (spca50x_flash_get_TOC(camera->pl,
436                                         &flash_file_count));
437         }
438         if (n < flash_file_count) {
439                 CHECK (spca50x_flash_get_file_name(camera->pl,
440                                         n, name));
441                 strncpy (info->file.name, name,
442                                 sizeof (info->file.name));
443
444                 CHECK (spca50x_flash_get_file_dimensions(
445                                         camera->pl, n, &w, &h));
446                 strcpy (info->file.type, GP_MIME_JPEG);
447                 info->file.width = w;
448                 info->file.height = h;
449                 info->preview.width = w/8;
450                 info->preview.height = h/8;
451         }
452         if (cam_has_sdram (camera->pl) && n >= flash_file_count ){
453                 CHECK (spca50x_sdram_get_file_info (camera->pl,
454                                         n-flash_file_count, &file));
455                 strncpy (info->file.name, filename, sizeof (info->file.name));
456                 if (file->mime_type == SPCA50X_FILE_TYPE_IMAGE) {
457                         strcpy (info->file.type, GP_MIME_JPEG);
458                         info->preview.width = 160;
459                         info->preview.height = 120;
460                 } else if (file->mime_type == SPCA50X_FILE_TYPE_AVI) {
461                         strcpy (info->file.type, GP_MIME_AVI);
462                         info->preview.width = 320;
463                         info->preview.height = 240;
464                 }
465                 info->file.width = file->width;
466                 info->file.height = file->height;
467
468         }
469         info->file.fields =
470                 GP_FILE_INFO_NAME | GP_FILE_INFO_TYPE
471                 | GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT;
472
473         info->file.mtime = 0;
474         info->file.fields |= GP_FILE_INFO_MTIME;
475
476         info->preview.fields =
477                 GP_FILE_INFO_TYPE | GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT;
478         strcpy (info->preview.type, GP_MIME_BMP);
479         return (GP_OK);
480 }
481
482 static int
483 delete_file_func (CameraFilesystem *fs, const char *folder,
484                   const char *filename, void *data, GPContext *context)
485 {
486         Camera *camera = data;
487         int n, c, flash_file_count;
488
489         /* FIXME deleting a single file for flash/card cams should work */
490         /* Get the file number from the CameraFileSystem */
491         CHECK (n =
492                gp_filesystem_number (camera->fs, folder, filename, context));
493
494         if (cam_has_flash(camera->pl) || cam_has_card(camera->pl) ) {
495                 CHECK (spca50x_flash_get_filecount
496                                         (camera->pl, &flash_file_count));
497         } else {
498                 /* should not happen really */
499                 return GP_ERROR;
500         }
501         if (n < flash_file_count) {
502                 return spca500_flash_delete_file (camera->pl, n);
503         }
504
505         CHECK (c = gp_filesystem_count (camera->fs, folder, context));
506         if (n + 1 != c) {
507                 const char *name;
508
509                 gp_filesystem_name (fs, "/", c - 1, &name, context);
510                 gp_context_error (context,
511                                   _("Your camera only supports deleting the "
512                                    "last file on the camera. In this case, this "
513                                    "is file '%s'."), name);
514                 return (GP_ERROR);
515         }
516         CHECK (spca50x_sdram_delete_file (camera->pl, n));
517         return GP_OK;
518 }
519
520 static int
521 delete_all_func (CameraFilesystem *fs, const char *folder, void *data,
522                  GPContext *context)
523 {
524         Camera *camera = data;
525
526         if (cam_has_sdram (camera->pl))
527                 CHECK (spca50x_sdram_delete_all (camera->pl));
528         if (cam_has_flash(camera->pl) || cam_has_card(camera->pl) )
529                 CHECK (spca50x_flash_delete_all (camera->pl, context));
530
531         return GP_OK;
532 }
533
534 static CameraFilesystemFuncs fsfuncs = {
535         .file_list_func = file_list_func,
536         .get_file_func = get_file_func,
537         .get_info_func = get_info_func,
538         .del_file_func = delete_file_func,
539         .delete_all_func = delete_all_func,
540 };
541
542 int
543 camera_init (Camera *camera, GPContext *context)
544 {
545         int ret = 0;
546         int x = 0;
547         char *model;
548
549         GPPortSettings settings;
550         CameraAbilities abilities;
551
552         /* First, set up all the function pointers */
553         camera->functions->exit = camera_exit;
554         camera->functions->summary = camera_summary;
555         camera->functions->about = camera_about;
556         camera->functions->capture = camera_capture;
557
558         CHECK (gp_port_get_settings (camera->port, &settings));
559         switch (camera->port->type) {
560                 case GP_PORT_USB:
561                         settings.usb.inep = 0x82;
562                         settings.usb.outep = 0x03;
563                         settings.usb.config = 1;
564                         settings.usb.interface = 0;
565                         settings.usb.altsetting = 0;
566
567                         CHECK (gp_port_set_settings (camera->port, settings));
568                         CHECK (gp_port_set_timeout (camera->port, TIMEOUT));
569
570                         break;
571                 default:
572                         gp_context_error (context,
573                                           _("Unsupported port type: %d. "
574                                             "This driver only works with USB "
575                                             "cameras.\n"), camera->port->type);
576                         return (GP_ERROR);
577                         break;
578         }
579
580         camera->pl = malloc (sizeof (CameraPrivateLibrary));
581         if (!camera->pl)
582                 return (GP_ERROR_NO_MEMORY);
583         memset (camera->pl, 0, sizeof (CameraPrivateLibrary));
584         camera->pl->gpdev = camera->port;
585         camera->pl->dirty_sdram = 1;
586         camera->pl->dirty_flash = 1;
587
588         /* What bridge chip is inside the camera? The gsmart mini is spca500
589          * based, while the others have a spca50xa */
590         gp_camera_get_abilities (camera, &abilities);
591         model = models[x].model;
592         while (model) {
593                 if (abilities.usb_vendor == models[x].usb_vendor
594                  && abilities.usb_product == models[x].usb_product) {
595                         int same;
596                         char *m = strdup( models[x].model );
597                         char *p = strchr (m, ':' );
598
599                         if (p) *p = ' ';
600                         same = !strcmp (m, abilities.model);
601                         free (m);
602                         if (same) {
603                                 camera->pl->bridge = models[x].bridge;
604                                 camera->pl->storage_media_mask =
605                                         models[x].storage_media_mask;
606                                 break;
607                         }
608                 }
609                 model = models[++x].model;
610         }
611
612         CHECK (spca50x_get_firmware_revision (camera->pl));
613         if (camera->pl->fw_rev > 1) {
614                 CHECK (spca50x_detect_storage_type (camera->pl));
615         }
616    
617         if (cam_has_flash(camera->pl) || cam_has_card(camera->pl) ) {
618                 if ((camera->pl->bridge == BRIDGE_SPCA504) ||
619                     (camera->pl->bridge == BRIDGE_SPCA504B_PD))
620                         CHECK (spca50x_flash_init (camera->pl, context));
621         }
622
623         if ((camera->pl->bridge == BRIDGE_SPCA504) ||
624             (camera->pl->bridge == BRIDGE_SPCA504B_PD)) {
625 /*              if (abilities.usb_vendor != 0x04fc && abilities.usb_product != 0x504a ) */
626                 if (!(abilities.usb_vendor == 0x04fc && abilities.usb_product == 0x504a ))
627                         ret = spca50x_reset (camera->pl);
628         }
629
630         if (ret < 0) {
631                 gp_context_error (context, _("Could not reset camera.\n"));
632                 free (camera->pl);
633                 camera->pl = NULL;
634
635                 return (ret);
636         }
637
638         /* Set up the CameraFilesystem */
639         return gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
640 }
641
642 static int
643 cam_has_sdram (CameraPrivateLibrary *pl)
644 {
645         return pl->storage_media_mask & SPCA50X_SDRAM;
646 }
647
648 static int
649 cam_has_flash (CameraPrivateLibrary *pl)
650 {
651         return pl->storage_media_mask & SPCA50X_FLASH;
652 }
653
654 static int
655 cam_has_card (CameraPrivateLibrary *pl)
656 {
657         return pl->storage_media_mask & SPCA50X_CARD;
658 }