diff options
Diffstat (limited to 'camlibs/mustek/core.c')
-rw-r--r-- | camlibs/mustek/core.c | 809 |
1 files changed, 809 insertions, 0 deletions
diff --git a/camlibs/mustek/core.c b/camlibs/mustek/core.c new file mode 100644 index 000000000..de996a5bc --- /dev/null +++ b/camlibs/mustek/core.c @@ -0,0 +1,809 @@ +/* + * Copyright © 1999/2000 by Henning Zabel <henning@uni-paderborn.de> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * gphoto driver for the Mustek MDC800 Digital Camera. The driver + * supports rs232 and USB. + */ + +#include <stdlib.h> +#include <string.h> + +#include <gphoto2/gphoto2-library.h> +#include <gphoto2/gphoto2-result.h> + +#include "core.h" +#include "print.h" + +#ifdef ENABLE_NLS +# include <libintl.h> +# undef _ +# define _(String) dgettext (GETTEXT_PACKAGE, String) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define _(String) (String) +# define N_(String) (String) +# endif +#else +# define _(String) (String) +# define N_(String) (String) +#endif + +/*---------------------- Funktion for Communication ------------------------ */ + +/* + * Send the Initial Command. If the device is rs232 this + * function will probe for the baudrate. + */ +static int +mdc800_sendInitialCommand (Camera *camera, char* answer) +{ + int baud_rates[3]={19200,57600,115200}; + int rate,ret; + char command [8]={COMMAND_BEGIN,COMMAND_INIT_CONNECT,0,0,0,COMMAND_END,0,0}; + + if (camera->port->type == GP_PORT_USB) + return mdc800_io_sendCommand_with_retry(camera->port,command,answer,8,1,1); + for (rate=0;rate<3;rate++) + { + GPPortSettings settings; + + ret = gp_port_get_settings(camera->port,&settings); + if (ret != GP_OK) return ret; + settings.serial.speed = baud_rates[rate]; + ret = gp_port_set_settings(camera->port, settings); + if (ret != GP_OK) return ret; + if (GP_OK==mdc800_io_sendCommand_with_retry(camera->port,command,answer,8,1,1)) { + printCoreNote("RS232 Baudrate probed at %d.\n",baud_rates[rate]); + return GP_OK; + } + printCoreError("Probing RS232 Baudrate with %d fails.\n",baud_rates[rate]); + } + printCoreError ("Probing failed completly.\n"); + return GP_ERROR_IO; +} + +/* + * Opens the Camera: + * (camera is already opened by gphoto2) + * (1) send Initial command + */ +int mdc800_openCamera (Camera *camera) +{ + char answer [8]; + int i,ret; + + if (camera->port->type == GP_PORT_USB) { + printCoreNote ("Device Registered as USB.\n"); + } else { + printCoreNote ("Device Registered as RS232. \n"); + } + + camera->pl = malloc(sizeof(struct _CameraPrivateLibrary)); + if (!camera->pl) + return GP_ERROR_NO_MEMORY; + camera->pl->system_flags_valid = 0; + camera->pl->memory_source = -1; + + /* Send initial command */ + ret = mdc800_sendInitialCommand(camera,answer); + if (ret != GP_OK) + { + printCoreError ("(mdc800_openCamera) can't send initial command.\n"); + return ret; + } + printCoreNote ("Firmware info (last 5 Bytes) : "); + for (i=0; i<8; i++) + printCoreNote ("%i ",(unsigned char) answer[i]); + printCoreNote ("\n"); + camera->pl->system_flags_valid=0; + camera->pl->memory_source=-1; + ret = mdc800_setDefaultStorageSource(camera); + if (ret != GP_OK) { + printCoreError ("(mdc800_openCamera) can't set Storage Source.\n"); + return ret; + } + return GP_OK; +} + +int mdc800_closeCamera (Camera *camera) +{ + if (camera->pl) { + free(camera->pl); + camera->pl = NULL; + } + return GP_OK; +} + + +/* + * Sets the camera speed to the defined value: + * 0: 19200, 1:57600, 2: 115200 + */ +int mdc800_changespeed (Camera *camera,int new) +{ + int baud_rate [3]={19200,57600,115200}; + GPPortSettings settings; + int ret,oldrate; + + printFnkCall ("(mdc800_changespeed) called.\n"); + if (camera->port->type != GP_PORT_SERIAL) /* USB ... */ + return GP_OK; + + gp_port_get_settings(camera->port,&settings); + + if (settings.serial.speed == baud_rate[new]) /* nothing to do */ + return GP_OK; + + for (oldrate=0;oldrate<sizeof(baud_rate)/sizeof(baud_rate[0]);oldrate++) + if (baud_rate[oldrate] == settings.serial.speed) + break; + + /* We did not find it? Can't happen? */ + if (oldrate == sizeof(baud_rate)/sizeof(baud_rate[0])) + return GP_ERROR_IO; + + /* Setting comunication speed */ + ret = mdc800_io_sendCommand(camera->port,COMMAND_CHANGE_RS232_BAUD_RATE,new,oldrate,0,0,0); + if (ret != GP_OK) + { + printCoreError ("(mdc800_changespeed) can't send first command.\n"); + return GP_ERROR_IO; + } + settings.serial.speed = baud_rate[new]; + ret = gp_port_set_settings(camera->port,settings); + if (ret != GP_OK) + { + printCoreError ("(mdc800_changespeed) Changing Baudrate fails.\n"); + return ret; + } + /* Second Command */ + ret = mdc800_io_sendCommand(camera->port,COMMAND_CHANGE_RS232_BAUD_RATE,new,new,0,0,0); + if (ret != GP_OK) + { + printCoreError ("(mdc800_changespeed) can't send second command.\n"); + return ret; + } + printCoreNote ("Set Baudrate to %d\n", baud_rate[new]); + return GP_OK; +} + +/* + * Get the current Bautrate + */ +int mdc800_getSpeed (Camera *camera, int *speed) +{ + int rate, ret, baud_rate [3]={19200,57600,115200}; + GPPortSettings settings; + + if (camera->port->type != GP_PORT_SERIAL) + return GP_ERROR_IO; + + ret = gp_port_get_settings(camera->port,&settings); + if (ret!=GP_OK) return ret; + + for (rate=0;rate<3;rate++) + if (settings.serial.speed == baud_rate[rate]) + break; + if (rate == 3) + return GP_ERROR_IO; + *speed = rate; + return GP_OK; +} + + +/* + * Sets Target + * 1: image, 2:thumbnail, 3:video, 4:not setting + */ +int mdc800_setTarget (Camera *camera,int value) +{ + return mdc800_io_sendCommand(camera->port,COMMAND_SET_TARGET,value,0,0,0,0); +} + + +/* + * Loads a thumbnail from the cam . + */ +int mdc800_getThumbnail (Camera *camera,int index, void **data, int *size) +{ + int ret; + + printFnkCall ("(mdc800_getThumbNail) called for %i . \n",index); + + *size = 4096; + *data = malloc(4096); + if (!*data) + return GP_ERROR_NO_MEMORY; + ret = mdc800_io_sendCommand(camera->port,COMMAND_GET_THUMBNAIL,index/100,(index%100)/10,index%10,*data,4096); + if (ret != GP_OK) + { + printCoreError ("(mdc800_getThumbNail) can't get Thumbnail.\n"); + return ret; + } + mdc800_correctImageData(*data,1,0,camera->pl->memory_source == 1); + return GP_OK; +} + + + +/* + * Load an Image from the cam .. + */ +int mdc800_getImage (Camera *camera, int nr, void **data, int *size) +{ + unsigned char buffer[3]; + int imagequality=-1; + int imagesize=0; + int ret; + + printFnkCall ("(mdc800_getImage) called for %i . \n",nr); + + ret = mdc800_setTarget (camera,1); + if (GP_OK != ret) { + printCoreError ("(mdc800_getImage) can't set Target. \n"); + return ret; + } + ret = mdc800_io_sendCommand(camera->port,COMMAND_GET_IMAGE_SIZE,nr/100,(nr%100)/10,nr%10,buffer,3); + if (ret != GP_OK) + { + printCoreError ("(mdc800_getImage) request for Imagesize of %i fails.\n",nr); + return ret; + } + + imagesize = buffer[0]*65536+buffer[1]*256+buffer[2]; + printCoreNote ("Imagesize of %i is %i ",nr,imagesize); + switch (imagesize/1024) + { + case 48: + imagequality=0; + printCoreNote ("(Economic Quality 506x384)\n"); + break; + case 128: + imagequality=1; + printCoreNote ("(Standard Quality 1012x768)\n"); + break; + case 320: + imagequality=2; + printCoreNote ("(High Quality 1012x768)\n"); + break; + case 4: + printCoreNote ("(ThumbNail ? 112x96)\n"); + imagequality=-1; + break; + default: + printCoreNote ("(not detected)\n"); + return 0; + } + *size = imagesize; + *data = malloc(imagesize); + ret = mdc800_io_sendCommand(camera->port,COMMAND_GET_IMAGE,nr/100,(nr%100)/10,nr%10,*data,imagesize); + if (ret != GP_OK) { + printCoreError ("(mdc800_getImage) request fails for Image %i.\n",nr); + return 0; + } + mdc800_correctImageData(*data,imagequality == -1,imagequality,camera->pl->memory_source == 1); + return GP_OK; +} + + + +/* ------ SystemStatus of the Camera ------------------------------------------/ */ + + +/* Load the Status from the camera if necessary */ +int mdc800_getSystemStatus (Camera *camera) +{ + int ret = GP_OK; + int tries = 3; + if (camera->pl->system_flags_valid) + return GP_OK; + fprintf(stderr,"mdc800_getSystemStatus entered...\n"); + while (tries--) { + ret = mdc800_io_sendCommand(camera->port,COMMAND_GET_SYSTEM_STATUS,0,0,0,camera->pl->system_flags,4); + if (ret == GP_OK) + break; + } + if (ret!=GP_OK) + { + printCoreError ("(mdc800_getSystemStatus) request fails.\n"); + return ret; + } + fprintf(stderr,"mdc800_getSystemStatus leaving.\n"); + camera->pl->system_flags_valid=1; + return GP_OK; +} + + +int mdc800_isCFCardPresent(Camera *camera) +{ + mdc800_getSystemStatus(camera); + if (camera->pl->system_flags_valid) + return (((unsigned char)camera->pl->system_flags[0]&1) == 0); + else + { + printCoreError ("(mdc800_isCFCardPresent) detection fails.\n"); + return 0; + } +} + + +int mdc800_isBatteryOk(Camera *camera) +{ + mdc800_getSystemStatus(camera); + return (((unsigned char)camera->pl->system_flags[0]&4) == 0)?1:0; +} + + +/* + * Gets CamMode. + * 0: Camera, 1: Playback, 2:VCam + */ +int mdc800_getMode(Camera *camera) +{ + mdc800_getSystemStatus(camera); + if (((unsigned char)camera->pl->system_flags[1]&16) == 0) + return (((unsigned char)camera->pl->system_flags[1]&32) == 0)?1:0; + else + return 2; +} + + +/* + * Return status of Flashlight. The + * answer is one of MDC800_FLASHLIGHT_ Mask. + */ +int mdc800_getFlashLightStatus(Camera *camera) +{ + mdc800_getSystemStatus(camera); + return ((unsigned char)camera->pl->system_flags[3]&7); +} + + +int mdc800_isLCDEnabled(Camera *camera) +{ + mdc800_getSystemStatus(camera); + return (((unsigned char)camera->pl->system_flags[1]&4) == 4); +} + + +int mdc800_isMenuOn(Camera *camera) +{ + mdc800_getSystemStatus(camera); + return (((unsigned char)camera->pl->system_flags[1]&1) == 1); +} + +int mdc800_isAutoOffEnabled(Camera *camera) +{ + mdc800_getSystemStatus(camera); + return (((unsigned char)camera->pl->system_flags[1]&8) == 8); +} + +/* ----- Other fine functions------------------------------------------------- */ + + +/* + * Sets Source of Images : + * 0: FlashCard, 1: Internal Memory + */ +int mdc800_setStorageSource (Camera *camera,int flag) +{ + int ret; + if (flag == camera->pl->memory_source) + return GP_OK; + + /* Check wether FlashCard is present */ + if ((flag == 0) && mdc800_isCFCardPresent (camera)) + { + printCoreNote ("There's is no FlashCard in the Camera !\n"); + return GP_OK; + } + printFnkCall ("(mdc800_setStorageSource) called with flag=%i\n",flag); + ret=mdc800_io_sendCommand(camera->port,COMMAND_SET_STORAGE_SOURCE,flag,0,0,0,0); + if (ret != GP_OK) + { + if (flag) + { + printCoreError ("Can't set InternalMemory as Input!\n"); + } + else + { + printCoreError ("Can't set FlashCard as Input!\n"); + } + return ret; + } + + printCoreNote ("Storage Source set to "); + if (flag) { + printCoreNote ("Internal Memory.\n"); + } else { + printCoreNote ("Compact Flash Card.\n"); + } + camera->pl->system_flags_valid=0; + camera->pl->memory_source=flag; + return GP_OK; +} + + +/* + * Sets the default storage source. + * Default means, that if there's a FlashCard, the Flashcard + * is used, else the InternalMemory + * + * If camera->pl->memory_source is set ( after driver has been closed ), + * this value will be used. + */ +int mdc800_setDefaultStorageSource (Camera *camera) +{ + int ret,source; + + if (camera->pl->memory_source != -1) + { + source=camera->pl->memory_source; + camera->pl->memory_source=-1; + } + else + { + source=mdc800_isCFCardPresent (camera)?0:1; + } + ret=mdc800_setStorageSource (camera,source); + if (ret!=GP_OK) + { + printCoreError ("(mdc800_setDefaultStorageSource) Setting Storage Source fails\n"); + return ret; + } + return GP_OK; +} + + +/* + * Returns what StorageSource is selected by the driver + * 0: FlashCard, 1: Internal + */ +int mdc800_getStorageSource(Camera *camera) +{ + if (camera->pl->memory_source == -1) + mdc800_setDefaultStorageSource(camera); + return camera->pl->memory_source; +} + + + +/* + * Sets Camera to Camera- or PlaybackMode + * m: 0 Camera, 1 Playback, 2:VCam (USB) + */ +int mdc800_setMode (Camera *camera,int m) +{ + int last=mdc800_getMode (camera); + int ret; +/* + if (mdc800_getMode () == m) + return 1; +*/ + switch (m) + { + case 0: + ret = mdc800_io_sendCommand(camera->port,COMMAND_SET_CAMERA_MODE,0,0,0,0,0); + if (ret != GP_OK) + { + printCoreError ("(mdc800_setMode) setting Camera Mode fails\n"); + return ret; + } + if (last != m) + printCoreNote ("Mode set to Camera Mode.\n"); + break; + + case 1: + ret = mdc800_io_sendCommand(camera->port,COMMAND_SET_PLAYBACK_MODE,0,0,0,0,0); + if (ret != GP_OK) + { + printCoreError ("(mdc800_setMode) setting Playback Mode fails\n"); + return ret; + } + if (last != m) + printCoreNote ("Mode set to Payback Mode.\n"); + break; + + } + camera->pl->system_flags_valid=0; + return GP_OK; +} + + +/* + * Sets up Flashlight. The waitForCommit waits a long + * time, to give the camera enough time to load the + * flashlight. + */ +int mdc800_setFlashLight (Camera* camera,int value) +{ + int command=0,redeye_flag=0,ret; + + if (mdc800_getFlashLightStatus (camera) == value) + return GP_OK; + + redeye_flag=(value&MDC800_FLASHLIGHT_REDEYE) != 0; + + if ((value&MDC800_FLASHLIGHT_ON) != 0) + command=COMMAND_SET_FLASHMODE_ON; + else if ((value&MDC800_FLASHLIGHT_OFF) != 0) + { + command=COMMAND_SET_FLASHMODE_OFF; + redeye_flag=0; + } + else + command=COMMAND_SET_FLASHMODE_AUTO; + + camera->pl->system_flags_valid=0; + ret = mdc800_io_sendCommand(camera->port,command,redeye_flag,0,0,0,0); + if (ret != GP_OK) + { + printCoreError ("(mdc800_setFlashLight) sending command fails.\n"); + return ret; + } + printCoreNote ("%s", mdc800_getFlashLightString(value)); + printCoreNote ("\n"); + return GP_OK; +} + +/* + * Gets a String with the Text of the Flashlight-Status + * depending on value + */ +char* mdc800_getFlashLightString (int value) +{ + switch (value) + { + case ( MDC800_FLASHLIGHT_REDEYE | MDC800_FLASHLIGHT_AUTO ) : + return _("FlashLight : Auto (RedEye Reduction)"); + case MDC800_FLASHLIGHT_AUTO : + return _("FlashLight : Auto"); + case ( MDC800_FLASHLIGHT_REDEYE | MDC800_FLASHLIGHT_ON ) : + return _("FlashLight : On (RedEye Reduction)"); + case MDC800_FLASHLIGHT_ON : + return _("FlashLight : On"); + case MDC800_FLASHLIGHT_OFF : + return _("FlashLight : Off"); + } + return _("FlashLight : undefined"); +} + + +/* + * Enable/Disable the LCD + */ +int mdc800_enableLCD (Camera*camera,int enable) +{ + int ret,command; + if (enable == mdc800_isLCDEnabled (camera)) + return GP_OK; + + if (enable) + command=COMMAND_SET_LCD_ON; + else + command=COMMAND_SET_LCD_OFF; + + camera->pl->system_flags_valid=0; + ret = mdc800_io_sendCommand (camera->port,command,0,0,0,0,0); + if (ret!=GP_OK) + { + printCoreError ("(mdc800_enableLCD) can't enable/disable LCD\n"); + return ret; + } + if (enable) + { + printCoreNote ("LCD is enabled\n"); + } + else + { + printCoreNote ("LCD is disabled\n"); + } + return GP_OK; +} + + +/* + * Shows the specified Image, the Camera has to + * be in Playback Mode ! + */ +int mdc800_playbackImage (Camera *camera,int nr ) +{ + int ret; + ret = mdc800_getMode (camera); + if (ret != GP_OK) + { + printCoreError ("(mdc800_showImage) camera must be in Playback Mode !"); + return ret; + } + + ret = mdc800_io_sendCommand (camera->port,COMMAND_PLAYBACK_IMAGE,nr/100,(nr%100)/10,nr%10,0,0); + if (ret!=GP_OK) + { + printCoreError ("(mdc800_showImage) can't playback Image %i \n",nr); + return ret; + } + return GP_OK; +} + +/* + * With ths function you can get information about, how many + * pictures can be stored in the free memory of the camera. + * + * h: High Quality, s: Standard Quality, e: Economy Quality + * If one of these Pointers are 0 the will be ignored. + */ +int mdc800_getRemainFreeImageCount (Camera *camera,int* h,int* s,int *e) +{ + unsigned char data [6]; + int ret; + + ret = mdc800_io_sendCommand (camera->port,COMMAND_GET_REMAIN_FREE_IMAGE_COUNT,0,0,0,(char*)data,6); + if (ret != GP_OK) + { + printCoreError ("(mdc800_getRemainFreeImageCount) Error sending Command.\n"); + return ret; + } + + if (h != 0) + (*h)=(int)((data[0]/16)*1000)+((data[0]%16)*100)+((data[1]/16)*10)+(data[1]%16); + if (s != 0) + (*s)=(int)((data[2]/16)*1000)+((data[2]%16)*100)+((data[3]/16)*10)+(data[3]%16); + if (e != 0) + (*e)=(int)((data[4]/16)*1000)+((data[4]%16)*100)+((data[5]/16)*10)+(data[5]%16); + return GP_OK; +} + + +/* + * Get Image Quallity + * 0: Economic, 1:Standard, 2:High + */ +int mdc800_getImageQuality (Camera *camera, char *retval) +{ + int ret; + ret = mdc800_io_sendCommand (camera->port,COMMAND_GET_IMAGE_QUALITY,0,0,0,retval,1); + if (ret!=GP_OK) + { + printCoreError ("(mdc800_getImageQuality) fails.\n"); + return ret; + } + return GP_OK; +} + + +/* + * Set Image Quality, return GP_OK if ok. + */ +int mdc800_setImageQuality (Camera *camera,int v) +{ + return mdc800_io_sendCommand (camera->port,COMMAND_SET_IMAGE_QUALITY,v,0,0,0,0); +} + + + +/* + * Set the WhiteBalance value + * 1:auto ,2:indoor, 4:indoor with flashlight, 8:outdoor + */ +int mdc800_setWB (Camera *camera, int v) +{ + return mdc800_io_sendCommand(camera->port,COMMAND_SET_WB,v,0,0,0,0); +} + + +/* + * Return the Exposure settings and W.B. + */ +int mdc800_getWBandExposure (Camera *camera,int* exp, int* wb) +{ + char retval[2]; + int ret; + + /* What's that here is a real diffenrence between USB and RS232 */ + int toggle= (camera->port->type == GP_PORT_USB); + + ret = mdc800_io_sendCommand(camera->port,COMMAND_GET_WB_AND_EXPOSURE,0,0,0,retval,2); + if (ret == GP_OK) + { + (*exp)=(unsigned char) retval[toggle]-2; + (*wb)=(unsigned char) retval[1-toggle]; + return 1; + } + printCoreError ("(mdc800_getWBandExposure) fails.\n"); + return 0; +} + + +/* + * Sets the Exposure Value + */ +int mdc800_setExposure (Camera *camera,int v) +{ + return mdc800_io_sendCommand(camera->port,COMMAND_SET_EXPOSURE,v+2,0,0,0,0); +} + +/* + * Sets the Exposure Mode + * 0: MTRX 1:CNTR + */ +int mdc800_setExposureMode (Camera *camera,int m) +{ + return mdc800_io_sendCommand (camera->port,COMMAND_SET_EXPOSURE_MODE,m,0,0,0,0); +} + + +/* + * return the Exposure Mode or -1 + */ +int mdc800_getExposureMode (Camera *camera,int *retval) +{ + unsigned char cretval; + int ret; + ret = mdc800_io_sendCommand (camera->port,COMMAND_GET_EXPOSURE_MODE,0,0,0,&cretval,1); + if (ret == GP_OK) + *retval = cretval; + return ret; +} + +/* + * Enable, Disable the Menu + */ +int mdc800_enableMenu (Camera *camera,int enable) +{ + char command=enable?COMMAND_SET_MENU_ON:COMMAND_SET_MENU_OFF; + + if (enable == mdc800_isMenuOn (camera)) + return GP_OK; + camera->pl->system_flags_valid=0; + return mdc800_io_sendCommand (camera->port,command,0,0,0,0,0); +} + +int mdc800_number_of_pictures (Camera *camera, int *nrofpics) +{ + unsigned char answer [2]; + int ret; + + printFnkCall ("(mdc800_number_of_pictures) called.\n"); + + ret= mdc800_setTarget (camera, 1); + if (ret != GP_OK) + { + printAPIError ("(mdc800_number_of_pictures) can't set Target\n"); + return ret; + } + +/* + if (!mdc800_setMode (1)) + { + printError ("(mdc800_number_of_pictures) can't set Mode\n"); + mdc800_close (); + return 0; + } +*/ + + ret = mdc800_io_sendCommand(camera->port,COMMAND_GET_NUM_IMAGES,0,0,0,(char*)answer,2); + if (ret != GP_OK) + { + printAPIError ("(mdc800_getNumberOfImages) request Number of Pictures fails.\n"); + return ret; + } + *nrofpics=(int)answer[0]*256+answer [1]; + return GP_OK; +} |