git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@6039 67ed7778-7388-44ab-90cf-0a291f65f57c
497 lines
14 KiB
C
497 lines
14 KiB
C
/**********************************************************************;
|
|
* Minolta Dimage V digital camera communication library *
|
|
* Copyright © 2000,2001 Gus Hartmann *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU General Public License as *
|
|
* published by the Free Software Foundation; either version 2 of *
|
|
* the License, or (at your option) any later version. *
|
|
* *
|
|
* This program 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 General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public *
|
|
* License along with this program; if not, write to the Free *
|
|
* Software Foundation, Inc., 59 Temple Place, Suite 330, *
|
|
* Boston, MA 02111-1307 USA *
|
|
* *
|
|
**********************************************************************/
|
|
|
|
#include "config.h"
|
|
|
|
#ifdef ENABLE_NLS
|
|
# include <libintl.h>
|
|
# undef _
|
|
# ifdef gettext_noop
|
|
# define _(String) dgettext (GETTEXT_PACKAGE, String)
|
|
# define N_(String) gettext_noop (String)
|
|
# else
|
|
# define _(String) (String)
|
|
# define N_(String) (String)
|
|
# endif
|
|
#else
|
|
# define _(String) (String)
|
|
# define N_(String) (String)
|
|
#endif
|
|
|
|
#include "dimagev.h"
|
|
|
|
#define GP_MODULE "dimagev"
|
|
|
|
int camera_id (CameraText *id)
|
|
{
|
|
#if defined HAVE_STRNCPY
|
|
strncpy(id->text, "minolta-dimagev", sizeof(id->text));
|
|
#else
|
|
strcpy(id->text, "minolta-dimagev");
|
|
#endif
|
|
|
|
return GP_OK;
|
|
}
|
|
|
|
int camera_abilities (CameraAbilitiesList *list)
|
|
{
|
|
CameraAbilities a;
|
|
|
|
memset(&a, 0, sizeof(a));
|
|
#if defined HAVE_STRNCPY
|
|
strncpy(a.model, "Minolta:Dimage V", sizeof(a.model));
|
|
#else
|
|
strcpy(a.model, "Minolta:Dimage V");
|
|
#endif
|
|
a.status = GP_DRIVER_STATUS_PRODUCTION;
|
|
a.port = GP_PORT_SERIAL;
|
|
a.speed[0] = 38400;
|
|
a.speed[1] = 0;
|
|
a.operations = GP_OPERATION_CAPTURE_IMAGE |
|
|
GP_OPERATION_CAPTURE_PREVIEW;
|
|
a.file_operations = GP_FILE_OPERATION_DELETE |
|
|
GP_FILE_OPERATION_PREVIEW;
|
|
a.folder_operations = GP_FOLDER_OPERATION_PUT_FILE |
|
|
GP_FOLDER_OPERATION_DELETE_ALL;
|
|
|
|
gp_abilities_list_append(list, a);
|
|
|
|
return GP_OK;
|
|
}
|
|
|
|
static int camera_exit (Camera *camera, GPContext *context)
|
|
{
|
|
/* Set the camera back into a normal mode. */
|
|
if (camera->pl) {
|
|
|
|
if (camera->pl->data) {
|
|
camera->pl->data->host_mode = (unsigned char) 0;
|
|
|
|
/* This will also send the host mode of zero. */
|
|
if ( dimagev_set_date(camera->pl) < GP_OK ) {
|
|
GP_DEBUG( "camera_init::unable to set camera to system time");
|
|
return GP_ERROR_IO;
|
|
}
|
|
free (camera->pl->data);
|
|
camera->pl->data = NULL;
|
|
}
|
|
|
|
if (camera->pl->status) {
|
|
free (camera->pl->status);
|
|
camera->pl->status = NULL;
|
|
}
|
|
|
|
if (camera->pl->info) {
|
|
free (camera->pl->info);
|
|
camera->pl->info = NULL;
|
|
}
|
|
|
|
free (camera->pl);
|
|
}
|
|
|
|
return GP_OK;
|
|
}
|
|
|
|
static int file_list_func (CameraFilesystem *fs, const char *folder,
|
|
CameraList *list, void *data, GPContext *context)
|
|
{
|
|
Camera *camera = data;
|
|
int ret;
|
|
|
|
if ( dimagev_get_camera_status(camera->pl) < GP_OK ) {
|
|
GP_DEBUG( "camera_file_list::unable to get camera status");
|
|
return GP_ERROR_IO;
|
|
}
|
|
|
|
if ((ret = gp_list_populate(list, DIMAGEV_FILENAME_FMT, camera->pl->status->number_images)) < GP_OK ) {
|
|
GP_DEBUG( "camera_file_list::unable to populate list");
|
|
return ret;
|
|
}
|
|
|
|
return GP_OK;
|
|
}
|
|
|
|
static int get_file_func (CameraFilesystem *fs, const char *folder,
|
|
const char *filename, CameraFileType type,
|
|
CameraFile *file, void *data, GPContext *context)
|
|
{
|
|
Camera *camera = data;
|
|
int file_number=0, result;
|
|
char buffer[128];
|
|
|
|
file_number = gp_filesystem_number(fs, folder, filename, context);
|
|
if (file_number < 0)
|
|
return (file_number);
|
|
|
|
switch (type) {
|
|
case GP_FILE_TYPE_NORMAL:
|
|
gp_file_set_mime_type (file, GP_MIME_JPEG);
|
|
gp_file_set_name (file, filename);
|
|
result = dimagev_get_picture (camera->pl, file_number + 1, file);
|
|
break;
|
|
case GP_FILE_TYPE_PREVIEW:
|
|
gp_file_set_mime_type (file, GP_MIME_PPM);
|
|
#if defined HAVE_SNPRINTF
|
|
snprintf(buffer, sizeof(buffer), DIMAGEV_THUMBNAIL_FMT, ( file_number + 1) );
|
|
#else
|
|
sprintf(buffer, DIMAGEV_THUMBNAIL_FMT, ( file_number + 1) );
|
|
#endif
|
|
gp_file_set_name (file, buffer);
|
|
result = dimagev_get_thumbnail (camera->pl, file_number + 1, file);
|
|
break;
|
|
default:
|
|
return (GP_ERROR_NOT_SUPPORTED);
|
|
}
|
|
|
|
if (result < 0) {
|
|
GP_DEBUG( "camera_file_get::unable to retrieve image file");
|
|
return result;
|
|
}
|
|
|
|
sleep(2);
|
|
return GP_OK;
|
|
}
|
|
|
|
static int delete_file_func (CameraFilesystem *fs, const char *folder,
|
|
const char *filename, void *data,
|
|
GPContext *context)
|
|
{
|
|
Camera *camera = data;
|
|
int file_number=0, ret;
|
|
|
|
file_number = gp_filesystem_number(camera->fs, folder, filename, context);
|
|
if (file_number < 0)
|
|
return (file_number);
|
|
|
|
ret = dimagev_delete_picture(camera->pl, (file_number + 1 ));
|
|
|
|
return (ret);
|
|
}
|
|
|
|
static int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context)
|
|
{
|
|
if (type != GP_CAPTURE_IMAGE)
|
|
return (GP_ERROR_NOT_SUPPORTED);
|
|
|
|
if ( dimagev_shutter(camera->pl) < GP_OK ) {
|
|
GP_DEBUG( "camera_capture::unable to open shutter");
|
|
return GP_ERROR_IO;
|
|
}
|
|
|
|
/* Now check how many pictures are taken, and return the last one. */
|
|
if ( dimagev_get_camera_status(camera->pl) != 0 ) {
|
|
GP_DEBUG( "camera_capture::unable to get camera status");
|
|
return GP_ERROR_IO;
|
|
}
|
|
|
|
#if defined HAVE_SNPRINTF
|
|
snprintf(path->folder, sizeof(path->folder), "/");
|
|
snprintf(path->name, sizeof(path->name), DIMAGEV_FILENAME_FMT, camera->pl->status->number_images);
|
|
#else
|
|
sprintf(path->folder, "/");
|
|
sprintf(path->name, DIMAGEV_FILENAME_FMT, camera->pl->status->number_images);
|
|
#endif
|
|
|
|
/* Tell the CameraFilesystem about this picture */
|
|
gp_filesystem_append (camera->fs, path->folder, path->name, context);
|
|
|
|
return GP_OK;
|
|
}
|
|
|
|
static int put_file_func (CameraFilesystem *fs, const char *folder,
|
|
CameraFile *file, void *data, GPContext *context)
|
|
{
|
|
Camera *camera = data;
|
|
|
|
return dimagev_put_file(camera->pl, file);
|
|
}
|
|
|
|
static int delete_all_func (CameraFilesystem *fs, const char *folder,
|
|
void *data, GPContext *context)
|
|
{
|
|
Camera *camera = data;
|
|
int ret;
|
|
|
|
ret = dimagev_delete_all(camera->pl);
|
|
|
|
return (ret);
|
|
}
|
|
|
|
static int camera_summary (Camera *camera, CameraText *summary, GPContext *context)
|
|
{
|
|
int i = 0, count = 0;
|
|
|
|
if ( dimagev_get_camera_status(camera->pl) < GP_OK ) {
|
|
GP_DEBUG( "camera_summary::unable to get camera status");
|
|
return GP_ERROR_IO;
|
|
}
|
|
|
|
if ( dimagev_get_camera_data(camera->pl) < GP_OK ) {
|
|
GP_DEBUG( "camera_summary::unable to get camera data");
|
|
return GP_ERROR_IO;
|
|
}
|
|
|
|
if ( dimagev_get_camera_info(camera->pl) < GP_OK ) {
|
|
GP_DEBUG( "camera_summary::unable to get camera info");
|
|
return GP_ERROR_IO;
|
|
}
|
|
|
|
dimagev_dump_camera_status(camera->pl->status);
|
|
dimagev_dump_camera_data(camera->pl->data);
|
|
dimagev_dump_camera_info(camera->pl->info);
|
|
|
|
/* Now put all of the information into a reasonably formatted string. */
|
|
/* i keeps track of the length. */
|
|
i = 0;
|
|
/* First the stuff from the dimagev_info_t */
|
|
#if defined HAVE_SNPRINTF
|
|
i = snprintf(summary->text, sizeof(summary->text),
|
|
#else
|
|
i = sprintf(summary->text,
|
|
#endif
|
|
_("Model:\t\t\tMinolta Dimage V (%s)\n"
|
|
"Hardware Revision:\t%s\nFirmware Revision:\t%s\n"),
|
|
camera->pl->info->model, camera->pl->info->hardware_rev,
|
|
camera->pl->info->firmware_rev);
|
|
|
|
if ( i > 0 ) {
|
|
count += i;
|
|
}
|
|
|
|
/* Now the stuff from dimagev_data_t */
|
|
#if defined HAVE_SNPRINTF
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count,
|
|
#else
|
|
i = sprintf(&(summary->text[count]),
|
|
#endif
|
|
_("Host Mode:\t\t%s\n"
|
|
"Exposure Correction:\t%s\n"
|
|
"Exposure Data:\t\t%d\n"
|
|
"Date Valid:\t\t%s\n"
|
|
"Date:\t\t\t%d/%02d/%02d %02d:%02d:%02d\n"
|
|
"Self Timer Set:\t\t%s\n"
|
|
"Quality Setting:\t%s\n"
|
|
"Play/Record Mode:\t%s\n"
|
|
"Card ID Valid:\t\t%s\n"
|
|
"Card ID:\t\t%d\n"
|
|
"Flash Mode:\t\t"),
|
|
|
|
( camera->pl->data->host_mode != (unsigned char) 0 ? _("Remote") : _("Local") ),
|
|
( camera->pl->data->exposure_valid != (unsigned char) 0 ? _("Yes") : _("No") ),
|
|
(signed char)camera->pl->data->exposure_correction,
|
|
( camera->pl->data->date_valid != (unsigned char) 0 ? _("Yes") : _("No") ),
|
|
( camera->pl->data->year < (unsigned char) 70 ? 2000 + (int) camera->pl->data->year : 1900 + (int) camera->pl->data->year ),
|
|
camera->pl->data->month, camera->pl->data->day, camera->pl->data->hour,
|
|
camera->pl->data->minute, camera->pl->data->second,
|
|
( camera->pl->data->self_timer_mode != (unsigned char) 0 ? _("Yes") : _("No")),
|
|
( camera->pl->data->quality_setting != (unsigned char) 0 ? _("Fine") : _("Standard") ),
|
|
( camera->pl->data->play_rec_mode != (unsigned char) 0 ? _("Record") : _("Play") ),
|
|
( camera->pl->data->valid != (unsigned char) 0 ? _("Yes") : _("No")), camera->pl->data->id_number );
|
|
|
|
if ( i > 0 ) {
|
|
count += i;
|
|
}
|
|
|
|
/* Flash is a special case, a switch is needed. */
|
|
switch ( camera->pl->data->flash_mode ) {
|
|
case 0:
|
|
#if defined HAVE_SNPRINTF
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count,
|
|
#else
|
|
i = sprintf(&(summary->text[count]),
|
|
#endif
|
|
_("Automatic\n"));
|
|
break;
|
|
case 1:
|
|
#if defined HAVE_SNPRINTF
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count,
|
|
#else
|
|
i = sprintf(&(summary->text[count]),
|
|
#endif
|
|
_("Force Flash\n"));
|
|
break;
|
|
case 2:
|
|
#if defined HAVE_SNPRINTF
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count,
|
|
#else
|
|
i = sprintf(&(summary->text[count]),
|
|
#endif
|
|
_("Prohibit Flash\n"));
|
|
break;
|
|
default:
|
|
#if defined HAVE_SNPRINTF
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count,
|
|
#else
|
|
i = sprintf(&(summary->text[count]),
|
|
#endif
|
|
_("Invalid Value ( %d )\n"), camera->pl->data->flash_mode);
|
|
break;
|
|
}
|
|
|
|
if ( i > 0 ) {
|
|
count += i;
|
|
}
|
|
|
|
/* Now for the information in dimagev_status_t */
|
|
#if defined HAVE_SNPRINTF
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count,
|
|
#else
|
|
i = sprintf(&(summary->text[count]),
|
|
#endif
|
|
_("Battery Level:\t\t%s\n"
|
|
"Number of Images:\t%d\n"
|
|
"Minimum Capacity Left:\t%d\n"
|
|
"Busy:\t\t\t%s\n"
|
|
"Flash Charging:\t\t%s\n"
|
|
"Lens Status:\t\t"),
|
|
( camera->pl->status->battery_level ? _("Not Full") : _("Full") ),
|
|
camera->pl->status->number_images,
|
|
camera->pl->status->minimum_images_can_take,
|
|
( camera->pl->status->busy ? _("Busy") : _("Idle") ),
|
|
( camera->pl->status->flash_charging ? _("Charging") : _("Ready") )
|
|
|
|
);
|
|
|
|
if ( i > 0 ) {
|
|
count += i;
|
|
}
|
|
|
|
/* Lens status is another switch. */
|
|
switch ( camera->pl->status->lens_status ) {
|
|
case 0:
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count, _("Normal\n"));
|
|
break;
|
|
case 1: case 2:
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count, _("Lens direction does not match flash light\n"));
|
|
break;
|
|
case 3:
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count, _("Lens is not connected\n"));
|
|
break;
|
|
default:
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count, _("Bad value for lens status %d\n"), camera->pl->status->lens_status);
|
|
break;
|
|
}
|
|
|
|
if ( i > 0 ) {
|
|
count += i;
|
|
}
|
|
|
|
/* Card status is another switch. */
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count, _("Card Status:\t\t"));
|
|
if ( i > 0 ) {
|
|
count += i;
|
|
}
|
|
|
|
switch ( camera->pl->status->card_status ) {
|
|
case 0:
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count, _("Normal"));
|
|
break;
|
|
case 1:
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count, _("Full"));
|
|
break;
|
|
case 2:
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count, _("Write-protected"));
|
|
break;
|
|
case 3:
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count, _("Unsuitable card"));
|
|
break;
|
|
default:
|
|
i = snprintf(&(summary->text[count]), sizeof(summary->text) - count, _("Bade value for card status %d"), camera->pl->status->card_status);
|
|
break;
|
|
}
|
|
|
|
if ( i > 0 ) {
|
|
count += i;
|
|
}
|
|
|
|
|
|
return GP_OK;
|
|
}
|
|
|
|
static int camera_about (Camera *camera, CameraText *about, GPContext *context)
|
|
{
|
|
#if defined HAVE_SNPRINTF
|
|
snprintf(about->text, sizeof(about->text),
|
|
#else
|
|
sprintf(about->text,
|
|
#endif
|
|
_("Minolta Dimage V Camera Library\n%s\nGus Hartmann <gphoto@gus-the-cat.org>\nSpecial thanks to Minolta for the spec."), DIMAGEV_VERSION);
|
|
|
|
return GP_OK;
|
|
}
|
|
|
|
int camera_init (Camera *camera, GPContext *context)
|
|
{
|
|
GPPortSettings settings;
|
|
|
|
/* First, set up all the function pointers */
|
|
camera->functions->exit = camera_exit;
|
|
camera->functions->capture = camera_capture;
|
|
camera->functions->summary = camera_summary;
|
|
camera->functions->about = camera_about;
|
|
|
|
GP_DEBUG( "initializing the camera");
|
|
|
|
camera->pl = malloc (sizeof (CameraPrivateLibrary));
|
|
if (!camera->pl)
|
|
return (GP_ERROR_NO_MEMORY);
|
|
memset (camera->pl, 0, sizeof (CameraPrivateLibrary));
|
|
camera->pl->dev = camera->port;
|
|
|
|
/* Configure the port */
|
|
gp_port_set_timeout(camera->port, 5000);
|
|
gp_port_get_settings(camera->port, &settings);
|
|
settings.serial.speed = 38400;
|
|
settings.serial.bits = 8;
|
|
settings.serial.parity = 0;
|
|
settings.serial.stopbits = 1;
|
|
gp_port_set_settings(camera->port, settings);
|
|
|
|
if ( dimagev_get_camera_data(camera->pl) < GP_OK ) {
|
|
GP_DEBUG( "camera_init::unable to get current camera data");
|
|
free (camera->pl);
|
|
camera->pl = NULL;
|
|
return GP_ERROR_IO;
|
|
}
|
|
|
|
if ( dimagev_get_camera_status(camera->pl) < GP_OK ) {
|
|
GP_DEBUG( "camera_init::unable to get current camera status");
|
|
free (camera->pl);
|
|
camera->pl = NULL;
|
|
return GP_ERROR_IO;
|
|
}
|
|
|
|
/* Let's make this non-fatal. An incorrect date doesn't affect much. */
|
|
if ( dimagev_set_date(camera->pl) < GP_OK ) {
|
|
GP_DEBUG( "camera_init::unable to set camera to system time");
|
|
}
|
|
|
|
/* Set up the filesystem */
|
|
gp_filesystem_set_list_funcs (camera->fs, file_list_func, NULL, camera);
|
|
gp_filesystem_set_file_funcs (camera->fs, get_file_func,
|
|
delete_file_func, camera);
|
|
gp_filesystem_set_folder_funcs (camera->fs, put_file_func,
|
|
delete_all_func, NULL, NULL, camera);
|
|
|
|
return GP_OK;
|
|
}
|
|
|