Files
libgphoto2/camlibs/spca50x/library.c
axxel f41df32817 fix white-space and indentation inconsistencies (second round)
This is basically a continuation of the work from #1002 but her for the
camlibs directory. The purpose was to replace spaces as a means for
indentation with tab characters.

Note: there are some files which are still offending the general
rule but are (mostly) consistent within themselves. I let them be for
the moment. Fixing them would basically replace the whole file.

Also: there are still a ton of whitespace related inconsistencies like
"x=10" vs "x = 10" or "func(10)" vs "func (10)".

This is a whitespace only change (if you include newlines as whitespace).
2024-09-15 10:53:41 +02:00

646 lines
18 KiB
C

/****************************************************************/
/* library.c - Gphoto2 library for cameras with sunplus spca50x */
/* chips */
/* Copyright (C) 2002, 2003 Till Adam */
/* */
/* Author: Till Adam <till@adam-lilienthal.de> */
/* */
/* This library is free software; you can redistribute it */
/* and/or modify it under the terms of the GNU Library General */
/* Public License as published by the Free Software Foundation; */
/* either version 2 of the License, or (at your option) any */
/* later version. */
/* */
/* This library is distributed in the hope that it will be */
/* useful, but WITHOUT ANY WARRANTY; without even the implied */
/* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
/* PURPOSE. See the GNU Library General Public License for */
/* more details. */
/* */
/* You should have received a copy of the GNU Library General */
/* Public License along with this library; if not, write to the */
/* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,*/
/* Boston, MA 02110-1301 USA */
/****************************************************************/
#define _DEFAULT_SOURCE
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <gphoto2/gphoto2.h>
#include <gphoto2/gphoto2-port.h>
#include "libgphoto2/i18n.h"
#include "spca50x.h"
#include "spca50x-flash.h"
#include "spca50x-sdram.h"
#define GP_MODULE "spca50x"
#define TIMEOUT 5000
#define SPCA50X_VERSION "0.1"
#define SPCA50X_LAST_MOD "02/09/03 - 23:14:11"
/* forward declarations */
static int file_list_func (CameraFilesystem *fs, const char *folder,
CameraList *list, void *data, GPContext *context);
static int get_file_func (CameraFilesystem *fs, const char *folder,
const char *filename, CameraFileType type,
CameraFile *file, void *user_data,
GPContext *context);
static int delete_file_func (CameraFilesystem *fs, const char *folder,
const char *filename, void *data,
GPContext *context);
static int delete_all_func (CameraFilesystem *fs, const char *folder,
void *data, GPContext *context);
static int get_info_func (CameraFilesystem *fs, const char *folder,
const char *filename, CameraFileInfo *info,
void *data, GPContext *context);
static int cam_has_sdram (CameraPrivateLibrary *pl);
static int cam_has_flash (CameraPrivateLibrary *pl);
static int cam_has_card (CameraPrivateLibrary *pl);
/* define what cameras we support */
static const struct
{
char *model;
int usb_vendor;
int usb_product;
SPCA50xBridgeChip bridge;
int storage_media_mask;
}
models[] =
{
/* firmware version 1 cams. */
{"Mustek:gSmart mini", 0x055f, 0xc220,
BRIDGE_SPCA500, SPCA50X_SDRAM },
{"Mustek:gSmart mini 2", 0x055f, 0xc420,
BRIDGE_SPCA504, SPCA50X_SDRAM },
{"Mustek:gSmart mini 3", 0x055f, 0xc520,
BRIDGE_SPCA504, SPCA50X_SDRAM },
{"So.:Show 301", 0x0ec7, 0x1008,
BRIDGE_SPCA504, SPCA50X_SDRAM },
{"Aiptek:Pencam", 0x04fc, 0x504a,
BRIDGE_SPCA504, SPCA50X_SDRAM | SPCA50X_FLASH },
/* same ids, different cam *sigh* */
{"Aiptek:Pencam without flash", 0x04fc, 0x504a,
BRIDGE_SPCA504, SPCA50X_SDRAM },
{"Medion:MD 5319", 0x04fc, 0x504a,
BRIDGE_SPCA504, SPCA50X_SDRAM | SPCA50X_FLASH },
{"nisis:Quickpix Qp3", 0x04fc, 0x504a,
BRIDGE_SPCA504, SPCA50X_SDRAM | SPCA50X_FLASH },
{"Trust:Spyc@m 500F FLASH", 0x04fc, 0x504a,
BRIDGE_SPCA504, SPCA50X_SDRAM | SPCA50X_FLASH },
/* The firmware 2 cams. Those can autodetect their storage type */
{"Aiptek:1.3 mega PocketCam", 0x04fc, 0x504b,
BRIDGE_SPCA504, 0 },
{"Maxell:Max Pocket", 0x04fc, 0x504b,
BRIDGE_SPCA504, 0 },
{"Aiptek:Smart Megacam", 0x04fc, 0x504b,
BRIDGE_SPCA504, 0 },
{"Benq:DC1300", 0x04a5, 0x3003,
BRIDGE_SPCA504, 0 },
/* Some other 500a cams with flash */
{"Trust:Familycam 300", 0x084d, 0x0003,
BRIDGE_SPCA500, SPCA50X_FLASH},
{"D-Link:DSC 350+", 0x084d, 0x0003,
BRIDGE_SPCA500, SPCA50X_FLASH},
{"Minton:S-Cam F5", 0x084d, 0x0003,
BRIDGE_SPCA500, SPCA50X_FLASH},
{"PureDigital:Ritz Disposable", 0x04fc, 0xffff,
BRIDGE_SPCA504B_PD, SPCA50X_FLASH},
{NULL, 0, 0, 0, 0}
};
int
camera_id (CameraText *id)
{
strcpy (id->text, "spca50x");
return (GP_OK);
}
int
camera_abilities (CameraAbilitiesList *list)
{
int x = 0;
char *ptr;
CameraAbilities a;
ptr = models[x].model;
while (ptr) {
memset (&a, 0, sizeof (a));
strcpy (a.model, ptr);
a.port = GP_PORT_USB;
a.speed[0] = 0;
a.status = GP_DRIVER_STATUS_TESTING;
a.file_operations = GP_FILE_OPERATION_PREVIEW
| GP_FILE_OPERATION_DELETE;
a.folder_operations = GP_FOLDER_OPERATION_DELETE_ALL;
a.usb_vendor = models[x].usb_vendor;
a.usb_product = models[x].usb_product;
if (models[x].bridge == BRIDGE_SPCA504) {
/* FIXME which cams can do it? */
if (a.usb_product == 0xc420
|| a.usb_product == 0xc520)
a.operations = GP_OPERATION_CAPTURE_IMAGE;
}
if (models[x].bridge == BRIDGE_SPCA504B_PD) {
a.operations = GP_OPERATION_CAPTURE_IMAGE;
}
if (models[x].bridge == BRIDGE_SPCA500) {
/* TEST enable capture for the DSC-350 style cams */
if (a.usb_vendor == 0x084d) {
a.operations = GP_OPERATION_CAPTURE_IMAGE;
}
}
gp_abilities_list_append (list, a);
ptr = models[++x].model;
}
return (GP_OK);
}
static int
camera_capture (Camera *camera, CameraCaptureType type,
CameraFilePath * path, GPContext *context)
{
struct SPCA50xFile *file;
CameraAbilities a;
/* Not all our cameras support capture */
gp_camera_get_abilities (camera, &a);
if (!(a.operations & GP_OPERATION_CAPTURE_IMAGE))
return GP_ERROR_NOT_SUPPORTED;
if (cam_has_flash(camera->pl))
{
int fc;
char tmp [14];
CHECK(spca500_flash_capture (camera->pl));
CHECK(spca50x_flash_get_TOC (camera->pl, &fc));
/* assume new pic is the last one in the cam...*/
CHECK(spca50x_flash_get_file_name (camera->pl, (fc - 1), tmp));
/* Add new image name to file list */
/* NOTE: these lines moved from below */
strncpy (path->name, tmp, sizeof (path->name) - 1);
path->name[sizeof (path->name) - 1] = '\0';
}
else
{
CHECK (spca50x_capture (camera->pl));
CHECK (spca50x_sdram_get_info (camera->pl));
CHECK (spca50x_sdram_get_file_info
(camera->pl, camera->pl->num_files_on_sdram - 1, &file));
/* Add new image name to file list */
/* NOTE: these lines moved from below */
strncpy (path->name, file->name, sizeof (path->name) - 1);
path->name[sizeof (path->name) - 1] = '\0';
}
/* Now tell the frontend where to look for the image */
strncpy (path->folder, "/", sizeof (path->folder) - 1);
path->folder[sizeof (path->folder) - 1] = '\0';
CHECK (gp_filesystem_append
(camera->fs, path->folder, path->name, context));
return GP_OK;
}
static int
camera_exit (Camera *camera, GPContext *context)
{
if (camera->pl) {
if (cam_has_flash (camera->pl) || cam_has_card (camera->pl))
spca50x_flash_close (camera->pl, context);
if (camera->pl->fats) {
free (camera->pl->fats);
camera->pl->fats = NULL;
}
if (camera->pl->flash_files) {
free (camera->pl->flash_files);
camera->pl->flash_files = NULL;
}
if (camera->pl->sdram_files) {
free (camera->pl->sdram_files);
camera->pl->sdram_files = NULL;
}
if (camera->pl->flash_toc) {
free (camera->pl->flash_toc);
camera->pl->flash_toc = NULL;
}
free (camera->pl);
camera->pl = NULL;
}
return (GP_OK);
}
static int
camera_summary (Camera *camera, CameraText *summary, GPContext *context)
{
char tmp[1024];
int flash_file_count;
if (cam_has_flash(camera->pl) || cam_has_card (camera->pl)) {
spca50x_flash_get_filecount(camera->pl, &flash_file_count);
snprintf (tmp, sizeof (tmp),
_("FLASH:\n Files: %d\n"), flash_file_count);
strcat (summary->text, tmp);
}
/* possibly get # pics, mem free, etc. if needed */
if (cam_has_sdram(camera->pl) && camera->pl->dirty_sdram) {
CHECK (spca50x_sdram_get_info (camera->pl));
snprintf (tmp, sizeof (tmp),
_("SDRAM:\n Files: %d\n Images: %4d\n Movies: %4d\nSpace used: %8d\nSpace free: %8d\n"),
camera->pl->num_files_on_sdram,
camera->pl->num_images,
camera->pl->num_movies,
camera->pl->size_used,
camera->pl->size_free);
strcat (summary->text, tmp);
}
return (GP_OK);
}
static int
camera_about (Camera *camera, CameraText *about, GPContext *context)
{
strcpy (about->text,
_("spca50x library v" SPCA50X_VERSION
" " SPCA50X_LAST_MOD "\n"
"Till Adam <till@adam-lilienthal.de>\n"
"Support for digital cameras with a sunplus spca50x chip "
"based on several other gphoto2 camlib modules and "
"the information kindly provided by Mustek.\n"
"\n"));
return (GP_OK);
}
static int
file_list_func (CameraFilesystem *fs, const char *folder,
CameraList *list, void *data, GPContext *context)
{
Camera *camera = data;
int i = 0, filecount = 0;
char temp_file[14];
if (cam_has_flash(camera->pl) || cam_has_card(camera->pl) )
{
CHECK (spca50x_flash_get_TOC(camera->pl, &filecount));
for (i=0; i<filecount; i++)
{
CHECK(spca50x_flash_get_file_name (camera->pl, i,
temp_file));
gp_list_append (list, temp_file, NULL);
}
}
if (cam_has_sdram(camera->pl)) {
if (camera->pl->dirty_sdram)
CHECK (spca50x_sdram_get_info (camera->pl));
for (i = 0; i < camera->pl->num_files_on_sdram; i++) {
if (camera->pl->sdram_files[i].name)
strncpy (temp_file, camera->pl->sdram_files[i].name, 12);
else
strcpy (temp_file, "BAD.BAD");
temp_file[12] = 0;
gp_list_append (list, temp_file, NULL);
}
}
return GP_OK;
}
static int
get_file_func (CameraFilesystem *fs, const char *folder,
const char *filename, CameraFileType type,
CameraFile *file, void *user_data, GPContext *context)
{
Camera *camera = user_data;
unsigned char *data = NULL;
int number, filetype, flash_file_count = 0;
unsigned int size;
CHECK (number =
gp_filesystem_number (camera->fs, folder, filename, context));
if (cam_has_flash(camera->pl) || cam_has_card(camera->pl) ) {
CHECK (spca50x_flash_get_filecount
(camera->pl, &flash_file_count));
}
switch (type) {
case GP_FILE_TYPE_NORMAL:
if ( number < flash_file_count) {
CHECK (spca50x_flash_get_file (camera->pl,
context, &data, &size,
number, 0));
CHECK (gp_file_set_mime_type
(file, GP_MIME_JPEG));
} else {
CHECK (spca50x_sdram_request_file
(camera->pl, &data, &size,
number-flash_file_count,
&filetype));
if (filetype == SPCA50X_FILE_TYPE_IMAGE) {
CHECK (gp_file_set_mime_type
(file, GP_MIME_JPEG));
} else if (filetype == SPCA50X_FILE_TYPE_AVI) {
CHECK (gp_file_set_mime_type
(file, GP_MIME_AVI));
}
}
break;
case GP_FILE_TYPE_PREVIEW:
if ( number < flash_file_count) {
CHECK (spca50x_flash_get_file (camera->pl,
context, &data, &size,
number, 1));
CHECK (gp_file_set_mime_type (file,
GP_MIME_BMP));
} else {
CHECK (spca50x_sdram_request_thumbnail
(camera->pl, &data, &size,
number-flash_file_count,
&filetype));
if (filetype == SPCA50X_FILE_TYPE_IMAGE) {
CHECK (gp_file_set_mime_type
(file, GP_MIME_BMP));
} else if (filetype == SPCA50X_FILE_TYPE_AVI) {
CHECK (gp_file_set_mime_type
(file, GP_MIME_JPEG));
}
}
break;
default:
return GP_ERROR_NOT_SUPPORTED;
}
if (!data)
return GP_ERROR;
return gp_file_set_data_and_size (file, (char *)data, size);
}
static int
get_info_func (CameraFilesystem *fs, const char *folder,
const char *filename, CameraFileInfo *info, void *data,
GPContext *context)
{
Camera *camera = data;
int n, flash_file_count = 0;
struct SPCA50xFile *file;
char name[14];
int w,h;
/* Get the file number from the CameraFileSystem */
CHECK (n =
gp_filesystem_number (camera->fs, folder, filename, context));
if (cam_has_flash(camera->pl) || cam_has_card(camera->pl) ) {
CHECK (spca50x_flash_get_TOC(camera->pl,
&flash_file_count));
}
if (n < flash_file_count) {
CHECK (spca50x_flash_get_file_name(camera->pl,
n, name));
CHECK (spca50x_flash_get_file_dimensions(
camera->pl, n, &w, &h));
strcpy (info->file.type, GP_MIME_JPEG);
info->file.width = w;
info->file.height = h;
info->preview.width = w/8;
info->preview.height = h/8;
}
if (cam_has_sdram (camera->pl) && n >= flash_file_count ){
CHECK (spca50x_sdram_get_file_info (camera->pl,
n-flash_file_count, &file));
if (file->mime_type == SPCA50X_FILE_TYPE_IMAGE) {
strcpy (info->file.type, GP_MIME_JPEG);
info->preview.width = 160;
info->preview.height = 120;
} else if (file->mime_type == SPCA50X_FILE_TYPE_AVI) {
strcpy (info->file.type, GP_MIME_AVI);
info->preview.width = 320;
info->preview.height = 240;
}
info->file.width = file->width;
info->file.height = file->height;
}
info->file.fields =
GP_FILE_INFO_TYPE
| GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT;
info->file.mtime = 0;
info->file.fields |= GP_FILE_INFO_MTIME;
info->preview.fields =
GP_FILE_INFO_TYPE | GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT;
strcpy (info->preview.type, GP_MIME_BMP);
return (GP_OK);
}
static int
delete_file_func (CameraFilesystem *fs, const char *folder,
const char *filename, void *data, GPContext *context)
{
Camera *camera = data;
int n, c, flash_file_count;
/* FIXME deleting a single file for flash/card cams should work */
/* Get the file number from the CameraFileSystem */
CHECK (n =
gp_filesystem_number (camera->fs, folder, filename, context));
if (cam_has_flash(camera->pl) || cam_has_card(camera->pl) ) {
CHECK (spca50x_flash_get_filecount
(camera->pl, &flash_file_count));
} else {
/* should not happen really */
return GP_ERROR;
}
if (n < flash_file_count) {
return spca500_flash_delete_file (camera->pl, n);
}
CHECK (c = gp_filesystem_count (camera->fs, folder, context));
if (n + 1 != c) {
const char *name;
gp_filesystem_name (fs, "/", c - 1, &name, context);
gp_context_error (context,
_("Your camera only supports deleting the "
"last file on the camera. In this case, this "
"is file '%s'."), name);
return (GP_ERROR);
}
CHECK (spca50x_sdram_delete_file (camera->pl, n));
return GP_OK;
}
static int
delete_all_func (CameraFilesystem *fs, const char *folder, void *data,
GPContext *context)
{
Camera *camera = data;
if (cam_has_sdram (camera->pl))
CHECK (spca50x_sdram_delete_all (camera->pl));
if (cam_has_flash(camera->pl) || cam_has_card(camera->pl) )
CHECK (spca50x_flash_delete_all (camera->pl, context));
return GP_OK;
}
static CameraFilesystemFuncs fsfuncs = {
.file_list_func = file_list_func,
.get_file_func = get_file_func,
.get_info_func = get_info_func,
.del_file_func = delete_file_func,
.delete_all_func = delete_all_func,
};
int
camera_init (Camera *camera, GPContext *context)
{
int ret = 0;
int x = 0;
char *model;
GPPortSettings settings;
CameraAbilities abilities;
/* First, set up all the function pointers */
camera->functions->exit = camera_exit;
camera->functions->summary = camera_summary;
camera->functions->about = camera_about;
camera->functions->capture = camera_capture;
CHECK (gp_port_get_settings (camera->port, &settings));
switch (camera->port->type) {
case GP_PORT_USB:
settings.usb.inep = 0x82;
settings.usb.outep = 0x03;
settings.usb.config = 1;
settings.usb.interface = 0;
settings.usb.altsetting = 0;
CHECK (gp_port_set_settings (camera->port, settings));
CHECK (gp_port_set_timeout (camera->port, TIMEOUT));
break;
default:
gp_context_error (context,
_("Unsupported port type: %d. "
"This driver only works with USB "
"cameras.\n"), camera->port->type);
return (GP_ERROR);
break;
}
camera->pl = calloc (1, sizeof (CameraPrivateLibrary));
if (!camera->pl)
return (GP_ERROR_NO_MEMORY);
camera->pl->gpdev = camera->port;
camera->pl->dirty_sdram = 1;
camera->pl->dirty_flash = 1;
/* What bridge chip is inside the camera? The gsmart mini is spca500
* based, while the others have a spca50xa */
gp_camera_get_abilities (camera, &abilities);
model = models[x].model;
while (model) {
if (abilities.usb_vendor == models[x].usb_vendor
&& abilities.usb_product == models[x].usb_product) {
int same;
char *m = strdup( models[x].model );
char *p = strchr (m, ':' );
if (p) *p = ' ';
same = !strcmp (m, abilities.model);
free (m);
if (same) {
camera->pl->bridge = models[x].bridge;
camera->pl->storage_media_mask =
models[x].storage_media_mask;
break;
}
}
model = models[++x].model;
}
CHECK (spca50x_get_firmware_revision (camera->pl));
if (camera->pl->fw_rev > 1) {
CHECK (spca50x_detect_storage_type (camera->pl));
}
if (cam_has_flash(camera->pl) || cam_has_card(camera->pl) ) {
if ((camera->pl->bridge == BRIDGE_SPCA504) ||
(camera->pl->bridge == BRIDGE_SPCA504B_PD))
CHECK (spca50x_flash_init (camera->pl, context));
}
if ((camera->pl->bridge == BRIDGE_SPCA504) ||
(camera->pl->bridge == BRIDGE_SPCA504B_PD)) {
/* if (abilities.usb_vendor != 0x04fc && abilities.usb_product != 0x504a ) */
if (!(abilities.usb_vendor == 0x04fc && abilities.usb_product == 0x504a ))
ret = spca50x_reset (camera->pl);
}
if (ret < 0) {
gp_context_error (context, _("Could not reset camera.\n"));
free (camera->pl);
camera->pl = NULL;
return (ret);
}
/* Set up the CameraFilesystem */
return gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
}
static int
cam_has_sdram (CameraPrivateLibrary *pl)
{
return pl->storage_media_mask & SPCA50X_SDRAM;
}
static int
cam_has_flash (CameraPrivateLibrary *pl)
{
return pl->storage_media_mask & SPCA50X_FLASH;
}
static int
cam_has_card (CameraPrivateLibrary *pl)
{
return pl->storage_media_mask & SPCA50X_CARD;
}