From 4bdcb030866c2ea25da548a79b832cc5c1ae0711 Mon Sep 17 00:00:00 2001 From: "Aurelien Croc (AP262C)" Date: Fri, 20 Jun 2003 01:14:24 +0000 Subject: [PATCH] I make too much modification under the QM150 Konica camera's driver, in particular, i implemented a lot of new functions I don't know why, but there is some problems between this driver and gtkam when we try to save one or all images. Else, no problems are mentionned. git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@6520 67ed7778-7388-44ab-90cf-0a291f65f57c --- camlibs/konica/qm150.c | 1497 ++++++++++++++++++++++++++++++-------- camlibs/konica/qm150.txt | 244 +++++-- 2 files changed, 1384 insertions(+), 357 deletions(-) diff --git a/camlibs/konica/qm150.c b/camlibs/konica/qm150.c index 662c3f14a..1b301840d 100644 --- a/camlibs/konica/qm150.c +++ b/camlibs/konica/qm150.c @@ -20,15 +20,27 @@ * * Modified by Aurélien Croc (AP²C) * In particular : fix some bugs, and implementation of advanced - * functions : delete some images, delete all images, capture new image + * functions : delete some images, delete all images, capture new image, + * update an image to the camera, get thumbnails, get information, get + * summary, get configuration, get manual, get about, get EXIF informations * */ + +/* NOTES : + * Becareful, image information number starts at 1 and finish at the + * max image number. But when you want to work on the images, you must + * read image informations, and check the real image number in the image + * information header and use this number with all functions !! + */ + #include "config.h" #include #include #include #include +#include +#include #ifdef ENABLE_NLS # include @@ -44,308 +56,96 @@ # define N_(String) (String) #endif +/* Functions codes */ +#define CAPTUREIMAGE_CMD2 0x30 +#define SETSPEED 0x42 +#define ERASEIMAGE_CMD1 0x45 +#define IMAGE_CMD2 0x46 +#define GETIMAGE_CMD1 0x47 +#define GETIMAGEINFO 0x49 +#define CAPTUREIMAGE_CMD1 0x52 +#define GETCAMINFO 0x53 +#define GETTHUMBNAIL_CMD1 0x54 +#define UPLOADDATA 0x55 +#define PING 0x58 -#define PING 0x58 -#define CAPTURE 0x52 -#define GETCAMINFO 0x53 -#define IMAGEINFO 0x49 -#define SETSPEED 0x42 -#define IMAGE 0x46 -#define GETDATA 0x47 -#define GETTHUMBNAIL 0x54 -#define ERAZEDATA 0x45 +/* Return codes */ +#define ESC 0x1b +#define ACK 0x06 +#define NACK 0x15 +#define NEXTFRAME 0x01 +#define EOT 0x04 -#define IMAGE 0x46 -#define NOSE 0x30 +/* Data section pointers */ +#define REC_MODE 0x01 +#define IMAGE_PROTECTED 0x01 -#define ESC 0x1b -#define ACK 0x06 -#define EOT 0x04 -#define CAMERAERROR 0x15 +#define GP_MODULE "Konica" +#define FILENAME "image%04d.jpg" +#define IMAGE_WIDTH 1360 +#define IMAGE_HEIGHT 1024 +#define PREVIEW_WIDTH 160 +#define PREVIEW_HEIGHT 120 +#define FILENAME_LEN 1024+128 -int -camera_id (CameraText *id) +#define ACK_LEN 1 +#define STATE_LEN 1 +#define CSUM_LEN 1 +#define INFO_BUFFER 256 +#define DATA_BUFFER 512 + +/* Image information pointers */ +#define PREVIEW_SIZE_PTR 0x4 +#define IMAGE_SIZE_PTR 0x8 +#define IMAGE_NUMBER 0xE +#define IMAGE_PROTECTION_FLAG 0x11 + +/* Camera information pointers */ +#define CAPACITY_PTR 0x3 +#define POWER_STATE_PTR 0x7 +#define AUTO_OFF_PTR 0x8 +#define CAMERA_MODE_PTR 0xA +#define LCD_STATE_PTR 0xB +#define ICON_STATE_PTR 0xC +#define FLASH_STATE_PTR 0xD +#define TIMER_PTR 0xE +#define RESOLUTION_PTR 0xF +#define WHITE_BALANCE_PTR 0x10 +#define EXPOSURE_TIME_PTR 0x11 +#define TAKEN_IMAGE_PTR 0x12 +#define FREE_IMAGE_PTR 0x14 +#define SHARPNESS_PTR 0x16 +#define COLOR_PTR 0x17 +#define RED_EYE_STATE_PTR 0x18 +#define FOCUS_PTR 0x19 +#define MACRO_PTR 0x1A +#define ZOOM_PTR 0x1B +#define CAPTURE_TYPE_PTR 0x1E +#define REC_DATE_DISP_PTR 0x1F +#define PLAY_DATE_DISP_PTR 0x20 +#define DATE_FORMAT_PTR 0x21 +#define TIMESTAMP_PTR 0x22 +extern unsigned char k_calculate_checksum (unsigned char *buf, + unsigned long int len); + +/** Local functions **********************************************************/ + +/* + * Check the integrity of datas + */ +unsigned char +k_calculate_checksum (unsigned char *buf, unsigned long int len) { - strcpy(id->text, "konica qm150"); - return (GP_OK); -} - -int -camera_abilities (CameraAbilitiesList *list) -{ - CameraAbilities a; - - memset(&a, 0, sizeof(a)); - strcpy(a.model, "Konica:Q-M150"); - a.status = GP_DRIVER_STATUS_EXPERIMENTAL; - a.port = GP_PORT_SERIAL; - a.speed[0] = 115200; - a.speed[1] = 0; - a.operations = GP_CAPTURE_IMAGE; - a.file_operations = GP_FILE_OPERATION_DELETE; - a.folder_operations = GP_FOLDER_OPERATION_DELETE_ALL; - gp_abilities_list_append(list, a); - 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; - unsigned char cmd[7], buf[512]; - int image_no, i, len, ret; - - image_no = gp_filesystem_number(fs, folder, filename, context); - if (image_no < 0) return image_no; - - image_no++; - cmd[0] = ESC; - cmd[1] = IMAGEINFO; - cmd[2] = 0x30 + ((image_no/1000)%10); - cmd[3] = 0x30 + ((image_no/100 )%10); - cmd[4] = 0x30 + ((image_no/10 )%10); - cmd[5] = 0x30 + ( image_no %10); - - ret = gp_port_write (camera->port, cmd, 6); - if (retport, buf, 256); - if (retport, cmd, 7); - if (retport, buf, 1); - if (ret < GP_OK) return ret; - if (buf[0] == CAMERAERROR) { - gp_context_error(context, _("This image doesn't exist.")); - return (GP_ERROR); - } - - gp_file_set_name (file, filename); - gp_file_set_mime_type (file, GP_MIME_JPEG); - for (i=0; i<(len+511)/512 ; i++) { - unsigned char csum; - int xret; - - xret = gp_port_read (camera->port, buf, 512); - if (xret < GP_OK) return xret; - ret = gp_port_read (camera->port, &csum, 1); - if (ret < GP_OK) return ret; - - ret = gp_file_append (file, buf, xret); - if (ret < GP_OK) return ret; - - /* acknowledge the packet */ - cmd[0] = ACK; - ret = gp_port_write (camera->port, cmd, 1); - if (ret < GP_OK) return ret; - - ret = gp_port_read (camera->port, buf, 1); - if (ret < GP_OK) return ret; - if (buf[0] == EOT) break; - - } - /* acknowledge the packet */ - cmd[0] = ACK; - ret = gp_port_write (camera->port, cmd, 1); - if (ret < GP_OK) return ret; - - return (GP_OK); -} - -static int -delete_file_func (CameraFilesystem *fs, const char *folder, const char *filename, - void *data, GPContext *context) -{ - Camera *camera = data; - unsigned char cmd[7], buf[512]; - int image_no, len, ret; - - image_no = gp_filesystem_number(fs, folder, filename, context); - if (image_no < 0) return image_no; - - image_no++; - cmd[0] = ESC; - cmd[1] = IMAGEINFO; - cmd[2] = 0x30 + ((image_no/1000)%10); - cmd[3] = 0x30 + ((image_no/100 )%10); - cmd[4] = 0x30 + ((image_no/10 )%10); - cmd[5] = 0x30 + ( image_no %10); - ret = gp_port_write (camera->port, cmd, 6); - if (retport, buf, 256); - if (retport, cmd, 7); - if (retport, buf, 1); - if (retport, cmd, 7); - if (retport, buf, 1); - if (ret */ - cmd[0] = ESC; - cmd[1] = GETCAMINFO; - ret = gp_port_write (camera->port, cmd, 2); - if (retport, buf, 256); - if (retport, cmd, 2); - if (retport, buf, 256); - if (retport, cmd, 2); - if (retport, buf, 256); - cmd[0] = ESC; - cmd[1] = CAPTURE; - cmd[2] = NOSE; - ret = gp_port_write (camera->port, cmd, 3); - if (retport, buf, 1); - if (retport, cmd, 2); - if (retport, buf, 256); - - - /* Find the name of the image captured */ - cmd[0] = ESC; - cmd[1] = GETCAMINFO; - ret = gp_port_write (camera->port, cmd, 2); - if (retport, buf, 256); - if (retname, "image%04d.jpg", (int) image_id); - strcpy (path->folder, "/"); - gp_filesystem_append (camera->fs, path->folder, - path->name, context); - return (GP_OK); -} - -static int -camera_about (Camera* camera, CameraText* about, GPContext *context) -{ - unsigned char cmd[2], buf[256]; - int ret; - - cmd[0] = ESC; - cmd[1] = GETCAMINFO; - ret = gp_port_write (camera->port, cmd, 2); - if (retport, buf, 256); - if (retport, cmd, sizeof(cmd)); + if (retport, buf, INFO_BUFFER); + if (ret */ + /* There is no audio support with this camera */ + info->audio.fields = GP_FILE_INFO_NONE; + /* Preview informations */ + info->preview.fields = GP_FILE_INFO_TYPE | GP_FILE_INFO_SIZE + | GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT; + strcpy (info->preview.type, GP_MIME_JPEG); + info->preview.size = ((buf[PREVIEW_SIZE_PTR] << 24) | + (buf[PREVIEW_SIZE_PTR+1] << 16) | (buf[PREVIEW_SIZE_PTR+2] << 8) + | buf[PREVIEW_SIZE_PTR+3]); + info->preview.width = PREVIEW_WIDTH; + info->preview.height = PREVIEW_HEIGHT; + + /* Image information */ + info->file.fields = GP_FILE_INFO_TYPE | GP_FILE_INFO_SIZE + | GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT | GP_FILE_INFO_NAME + | GP_FILE_INFO_PERMISSIONS; + strcpy (info->file.type, GP_MIME_JPEG); + info->file.size = ((buf[IMAGE_SIZE_PTR] << 24) | + (buf[IMAGE_SIZE_PTR+1] << 16) | (buf[IMAGE_SIZE_PTR+2] << 8) + | buf[IMAGE_SIZE_PTR+3]); + info->file.width = IMAGE_WIDTH; + info->file.height = IMAGE_HEIGHT; + snprintf (info->file.name, sizeof (info->file.name),(char *) FILENAME, + image_no); + if (buf[IMAGE_PROTECTION_FLAG] == IMAGE_PROTECTED) + info->file.permissions = GP_FILE_PERM_READ; + else + info->file.permissions = GP_FILE_PERM_ALL; + return (GP_OK); +} + +/* + * Get data from the camera + * type = GP_FILE_TYPE_NORMAL, GP_FILE_TYPE_PREVIEW or GP_FILE_TYPE_EXIF + */ +static int +k_getdata (int image_no, int type, unsigned int len, void *data, + unsigned char *d, GPContext *context) +{ + Camera *camera = data; + unsigned char ack,state, cmd[7], buf[DATA_BUFFER], *buffer=d; + unsigned int id=0, bytes_read=0, i; + int ret; + + cmd[0] = ESC; + cmd[1] = GETIMAGE_CMD1; + if (type != GP_FILE_TYPE_NORMAL) + cmd[1] = GETTHUMBNAIL_CMD1; + cmd[2] = IMAGE_CMD2; + cmd[3] = 0x30 + ((image_no/1000)%10); + cmd[4] = 0x30 + ((image_no/100 )%10); + cmd[5] = 0x30 + ((image_no/10 )%10); + cmd[6] = 0x30 + ( image_no %10); + + ret = gp_port_write (camera->port, cmd, sizeof(cmd)); + if (retport, &ack, ACK_LEN); + if (ret < GP_OK) return ret; + if (ack == NACK) { + gp_context_error(context, _("This preview doesn't exist.")); + return (GP_ERROR); + } + + /* Download the required image */ + if (type == GP_FILE_TYPE_NORMAL) + id = gp_context_progress_start (context, len, + _("Downloading image...")); + for (i=0; i <= (len+DATA_BUFFER-1)/DATA_BUFFER ; i++) { + unsigned char csum; + int xret; + + xret = gp_port_read (camera->port, buf, DATA_BUFFER); + if (xret < GP_OK) { + if (type == GP_FILE_TYPE_NORMAL) + gp_context_progress_stop (context, id); + return xret; + } + ret = gp_port_read (camera->port, &csum, CSUM_LEN); + if (ret < GP_OK) { + if (type == GP_FILE_TYPE_NORMAL) + gp_context_progress_stop (context, id); + return ret; + } + if ((k_calculate_checksum(buf, DATA_BUFFER)) != csum) { + if (type == GP_FILE_TYPE_NORMAL) + gp_context_progress_stop (context, id); + /* acknowledge the packet */ + ack = NACK; + ret = gp_port_write (camera->port, &ack, ACK_LEN); + if (ret < GP_OK) + return ret; + gp_context_error(context, _("Datas has corrupted.")); + return (GP_ERROR_CORRUPTED_DATA); + } + if ((len - bytes_read) > DATA_BUFFER) { + memcpy((char *)buffer, buf, xret); + (unsigned int)buffer += DATA_BUFFER; + } else { + memcpy((char *)buffer, buf, (len - bytes_read)); + (unsigned int)buffer += len - bytes_read; + } + + /* acknowledge the packet */ + ack = ACK; + ret = gp_port_write (camera->port, &ack, ACK_LEN); + if (ret < GP_OK) { + if (type == GP_FILE_TYPE_NORMAL) + gp_context_progress_stop (context, id); + return ret; + } + ret = gp_port_read (camera->port, &state, STATE_LEN); + if (ret < GP_OK) { + if (type == GP_FILE_TYPE_NORMAL) + gp_context_progress_stop (context, id); + return ret; + } + if (state == EOT) + break; + bytes_read += DATA_BUFFER; + if (type == GP_FILE_TYPE_NORMAL) + gp_context_progress_update (context, id, bytes_read); + } + /* acknowledge the packet */ + ack = ACK; + ret = gp_port_write (camera->port, &ack, ACK_LEN); + if (ret < GP_OK) { + if (type == GP_FILE_TYPE_NORMAL) + gp_context_progress_stop (context, id); + return ret; + } + if (type == GP_FILE_TYPE_NORMAL) + gp_context_progress_stop (context, id); + return (GP_OK); +} + + +/** Get and delete files *****************************************************/ + +/* + * Get images, thumbnails or EXIF datas + */ +static int +get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, + CameraFileType type, CameraFile *file, void *data, + GPContext *context) +{ + unsigned char *d,*thumbnail; + int image_no, len, ret, image_number; + long long_len; + CameraFileInfo file_info; + exifparser exifdat; + GP_DEBUG ("*** ENTER: get_file_func ***"); + + image_no = gp_filesystem_number(fs, folder, filename, context); + if (image_no < 0) return image_no; + + /* Search the image informations */ + image_no++; + ret = k_info_img (image_no, data, (CameraFileInfo *)&file_info, + &image_number); + image_no = image_number; + if (ret < GP_OK) + return ret; + + switch (type) { + case GP_FILE_TYPE_NORMAL: + len = file_info.file.size; + if (!(d = (unsigned char *)malloc(len))) + return (GP_ERROR_NO_MEMORY); + ret = k_getdata(image_no, GP_FILE_TYPE_NORMAL,len, + data, d, context); + if (ret < GP_OK) { + free(d); + return ret; + } + break; + case GP_FILE_TYPE_PREVIEW: + len = file_info.preview.size; + long_len = (long)len; + if (!(d = (unsigned char *)malloc(len))) + return (GP_ERROR_NO_MEMORY); + ret = k_getdata(image_no, GP_FILE_TYPE_PREVIEW, len, + data, d, context); + if (ret < GP_OK) { + free(d); + return ret; + } + exifdat.header = d; + exifdat.data = d+12; + thumbnail = exif_get_thumbnail_and_size(&exifdat, + &long_len); + free(d); + d = thumbnail; + if (ret < GP_OK) { + free(d); + return ret; + } + break; + case GP_FILE_TYPE_EXIF: + len = file_info.preview.size; + if (!(d = (unsigned char *)malloc(len))) + return (GP_ERROR_NO_MEMORY); + ret = k_getdata(image_no, GP_FILE_TYPE_EXIF, len, + data, d, context); + if (ret < GP_OK) { + free(d); + return ret; + } + break; + default: + gp_context_error(context, + _("This is not supported by this camera !")); + return (GP_ERROR_NOT_SUPPORTED); + } + gp_file_set_name (file, filename); + gp_file_set_mime_type (file, GP_MIME_JPEG); + if (type == GP_FILE_TYPE_EXIF) + gp_file_set_type (file, GP_FILE_TYPE_EXIF); + ret = gp_file_append(file, d, len); + free(d); + return (ret); +} + +/* + * Delete one image + * The image mustn't be protected + */ +static int +delete_file_func (CameraFilesystem *fs, const char *folder, + const char *filename, void *data, GPContext *context) +{ + Camera *camera = data; + CameraFileInfo file_info; + unsigned char cmd[7], ack; + int image_no, ret; + + GP_DEBUG ("*** ENTER: delete_file_func ***"); + + image_no = gp_filesystem_number(fs, folder, filename, context); + if (image_no < 0) return image_no; + + image_no++; + ret = k_info_img (image_no, data, (CameraFileInfo *)&file_info, + &image_no); + if (ret < GP_OK) + return ret; + + /* Now, check if the image isn't protected */ + if (file_info.file.permissions == GP_FILE_PERM_READ) { + gp_context_error(context, _("Image %s is delete protected."), + filename); + return (GP_ERROR); + } + + /* Erase the image */ + cmd[0] = ESC; + cmd[1] = ERASEIMAGE_CMD1; + cmd[2] = IMAGE_CMD2; + cmd[3] = 0x30 + ((image_no/1000)%10); + cmd[4] = 0x30 + ((image_no/100 )%10); + cmd[5] = 0x30 + ((image_no/10 )%10); + cmd[6] = 0x30 + ( image_no %10); + ret = gp_port_write (camera->port, cmd, sizeof(cmd)); + if (retport, &ack, ACK_LEN); + if (retport, cmd, sizeof(cmd)); + if (retport, &ack, ACK_LEN); + if (retport, cmd, sizeof(cmd)); + if (retport, &ack, ACK_LEN); + if (retport, &state, STATE_LEN); + if (retport, &d[i*DATA_BUFFER], + (len - len_sent)); + if (retport, buf, (DATA_BUFFER - + (len - len_sent))); + if (retport, &d[i*DATA_BUFFER], + DATA_BUFFER); + if (retport, &sum, CSUM_LEN); + if (retport, &state, STATE_LEN); + if (retport, &ack, ACK_LEN); + if (retport, cmd, 2); + if (retport, buf, INFO_BUFFER); + nbr_images = (buf[FREE_IMAGE_PTR] << 8) | (buf[FREE_IMAGE_PTR+1]); + images_taken = (buf[TAKEN_IMAGE_PTR] << 8) | (buf[TAKEN_IMAGE_PTR+1]); + + /* Capture the image */ + cmd[0] = ESC; + cmd[1] = CAPTUREIMAGE_CMD1; + cmd[2] = CAPTUREIMAGE_CMD2; + ret = gp_port_write (camera->port, cmd, sizeof(cmd)); + if (retport, &ack, ACK_LEN); + if (retport)) == GP_OK) + break; + } + if (ret < GP_OK) { + gp_context_error(context, _("No answer from the camera.")); + return (GP_ERROR); + } + + /* Now register new image */ + images_taken++; + sprintf (path->name, FILENAME, (unsigned int) images_taken); + return (GP_OK); +} + +/* + * Get informations about an image + */ +static int +get_info_func (CameraFilesystem *fs, const char *folder, const char *filename, + CameraFileInfo *info, void *data, GPContext *context) +{ + int image_no; + + GP_DEBUG ("*** ENTER: get_info_func ***"); + + image_no = gp_filesystem_number(fs, folder, filename, context); + if (image_no < 0) + return image_no; + image_no++; + + return (k_info_img(image_no, data, info, NULL)); +} + + +/** Driver base functions ****************************************************/ + +/* + * Create the image list + */ +static int +file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, + void *data, GPContext *context) +{ + Camera *camera = data; + unsigned char cmd[2], buf[INFO_BUFFER]; + int num, ret; + + GP_DEBUG ("*** ENTER: file_list_func ***"); + + cmd[0] = ESC; + cmd[1] = GETCAMINFO; + ret = gp_port_write (camera->port, cmd, sizeof(cmd)); + if (retport, buf, INFO_BUFFER); + if (retport, cmd, sizeof(cmd)); + if (retport, buf, INFO_BUFFER); + if (retport, cmd, sizeof(cmd)); + if (retport, buf, INFO_BUFFER); + if (rettext, sizeof(text->text), + _("Model: %s\n" + "Capacity: %iMo\n" + "Power: %s\n" + "Auto Off Time: %imin\n" + "Mode: %s\n" + "Images: %i/%i\n" + "Date display: %s\n" + "Date and Time: %s\n"), + "Konica Q-M150",capacity, + power,autopoweroff,mode, + image_taken,image_remained, + date_disp,date); + return (GP_OK); +} + +/** Camera's driver informations *********************************************/ + +/* + * Say somethings about driver's authors + */ +static int +camera_about (Camera* camera, CameraText* about, GPContext *context) +{ + snprintf(about->text,sizeof(about->text),_("Konica Q-M150 Library\n" + "Marcus Meissner \n" + "Aurelien Croc (AP2C) \n" + "http://www.ap2c.com\n" + "Support for the french Konica Q-M150.")); + return(GP_OK); +} + +/* + * just say some things about this driver + */ +static int +camera_manual (Camera *camera, CameraText *manual, GPContext *context) +{ + snprintf(manual->text,sizeof(manual->text), + _("About Konica Q-M150:\n" + "This camera does not support to do any changes\n" + "from the outside. So in the configuration, you could\n" + "just see what it is configured on the camera\n" + "but you can't change anything.\n\n" + "If you have some issues with this driver, please\n" + "send an e-mail to the authors of this driver.\n\n" + "Thanks to use GPhoto2 and UNIX/Linux Operating systems.\n")); + return (GP_OK); +} + +/* + * Camera's identification + */ +int +camera_id (CameraText *id) +{ + strcpy(id->text, "konica qm150"); + return (GP_OK); +} + +/* + * List all camera's abilities + */ +int +camera_abilities (CameraAbilitiesList *list) +{ + CameraAbilities a; + + memset(&a, 0, sizeof(a)); + strcpy(a.model, "Konica:Q-M150"); + a.status = GP_DRIVER_STATUS_EXPERIMENTAL; + a.port = GP_PORT_SERIAL; + a.speed[0] = 115200; + a.speed[1] = 0; + a.operations = GP_OPERATION_CAPTURE_IMAGE | + GP_OPERATION_CAPTURE_PREVIEW | GP_OPERATION_CONFIG; + a.file_operations = GP_FILE_OPERATION_DELETE | + GP_FILE_OPERATION_EXIF | GP_FILE_OPERATION_PREVIEW; + a.folder_operations = GP_FOLDER_OPERATION_DELETE_ALL | + GP_FOLDER_OPERATION_PUT_FILE; + gp_abilities_list_append(list, a); + return (GP_OK); +} + +/** Camera's initialization **************************************************/ +/* + * Initialization of the camera + */ int camera_init (Camera *camera, GPContext *context) { @@ -371,14 +1264,20 @@ camera_init (Camera *camera, GPContext *context) /* First, set up all the function pointers. */ camera->functions->capture = camera_capture; - /* camera->functions->about = camera_about; */ + camera->functions->about = camera_about; + camera->functions->get_config = camera_get_config; + camera->functions->set_config = camera_set_config; + camera->functions->summary = camera_summary; + camera->functions->manual = camera_manual; /* Now, tell the filesystem where to get lists, files and info */ gp_filesystem_set_list_funcs (camera->fs, file_list_func, NULL, camera); gp_filesystem_set_info_funcs (camera->fs, get_info_func, NULL, camera); - gp_filesystem_set_file_funcs (camera->fs, get_file_func, delete_file_func, camera); - gp_filesystem_set_folder_funcs (camera->fs, NULL, delete_all_func, NULL, 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); /* * The port is already provided with camera->port (and diff --git a/camlibs/konica/qm150.txt b/camlibs/konica/qm150.txt index 71d878d91..9cb0045ff 100644 --- a/camlibs/konica/qm150.txt +++ b/camlibs/konica/qm150.txt @@ -1,64 +1,192 @@ -The Konica Q-M150 uses a pretty simple serial protocol. - -1. Ping command - - Command: ESC X (1B 58) - Reply: ACK (06) - - Used to test the baudrate. - -2. Set Baudrate - - Command: ESC B (1B 42 3x) - Reply: ACK (06) - - Sets the baudrate. is an ascii number from 0 to 4. - I suspect the mapping is as follows: - 0 - 9600 - 1 - 19200 - 2 - 38400 - 3 - 57600 - 4 - 115200 - - The camera switches baudrate directly after sending the ACK. - -3. Get Camera Info - - Command: ESC S (1B 53) - Reply: 256 byte of data, sample: - 03 03 02 00 1F 02 00 01 07 08 01 00 01 00 00 00 00 00 00 83 - 00 59 00 00 01 00 00 00 01 01 00 01 00 00 23 BD 9C 28 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ... more 00 ... - - The 00 00 00 83 appear to be the number of images. - -4. Get Image Info - - Command: ESC I (1B 49 3x 3x 3x 3x) - Reply: 256 byte of data: - - 03 03 00 84 00 00 20 69 00 01 A6 B1 02 DC 00 83 01 00 00 00 - ... more 00 ... - - is an ascii number, "30 30 34 32" stands for 42. - Image start at 1. +Functions codes : +all functions are preceded by escape code (0x1B). + - 0x58 = ping (receive 1 byte = ACK or anything else will be an error) + - 0x53 = get camera informations (receive 256 bytes of informations. Details after this list) + - 0x49 0x3X 0x3X 0x3X 0x3X = get image informations (receive 256 bytes of informations. Details after this list) + - 0x42 0x3X = Set broadcast speed : + 0x30 = 9600 bauds + 0x31 = 19200 bauds + 0x32 = 38400 bauds + 0x33 = 57600 bauds + 0x34 = 115200 bauds + (In all case, if ok, receive an ACK (1 byte)) + - 0x47 0x46 0x3X 0x3X 0x3X 0x3X = Get image + receive 1 byte which contains the ACK (0x6 = all is ok | 0x15 = there is an error) + And by cycle : + receive a part of the picture (512 bytes) + receive a checksum (1 byte) + we must send the result of the checksum (0x6 = All os OK | 0x15 = seems to be an error is happened) + receive information about the transmission (1 byte) + 0x1 = next buffer will be transmetted just after + so we must loop + 0x4 = finished : we must send an ACK (1 byte) and it's finished + - 0x45 0x46 0x3X 0x3X 0x3X 0x3X = Delete an image (Receive an ACK (1 byte)) Here, we must check if image isn't protected + - 0x45 0x46 0x30 0x30 0x30 0x30 = Delete all images (Receive an ACK (1 byte)) + - 0x52 0x90 = Capture an image (Receive an ACK (1 byte)) Here, the camera must be in rec mode ! - Length is in the "00 01 A6 B1" sequence. +Camera's Information buffer : +0x00 - 0x02 = Seems to be a signature ? 0x03 0x03 0x02 +0x03 - 0x04 = Len of the memory card (or just 0x04 ?!?) +0x05 - 0x06 = Ne serait-ce pas la taille du buffer de données ?! NON !!! ERRONE +0x07 = AC / pile (0 = pile | 1 = AC) +0x08 - 0x09 = Auto-extinction (en secondes) +0x0A = camera's mode (0x0 = play mode | 0x1 = rec mode) +0x0B = LCD (0 = on | 1 = off) +0x0C = Affichage de la barre sur l'écran du numérique (1 = absente | 0 = présente) +0x0D = Flash (0 = automatique | 1 = forcé | 2 = pas de flash) +0x0E = Minuterie (0 = off | 1 = on) +0x0F = Qualité d'enregistrement (0 = Normal | 1 = forte qualité | 2 = économique) +0x10 = white balance (0 = auto | 2 = office | 1 = Day-lt) +0x11 = exposure : 0 à 8 = 0, 0.3, 0.5, 0.8, 1.0, 1.3, 1.5, 1.8, 2.0 + 0xf8 à 0xff = -2.0, -1.8, -1.5, -1.3, -1.0, -0.8, -0.5, -0.3 +0x12 - 0x13 = Images taken (MBR and LBR) +0x14 - 0x15 = Image remaining (MBR and LBR) +0x16 = Sharpness (0 = auto | 1 = sharp | 2 = soft) +0x17 = Color (0 = auto | 1 = light | 2 = deep | 3 = B/W | 4 = Sepia) +0x18 = Pre-flash (0 = off | 1 = on) +0x19 = Focus (0 = auto | 1 = 2.0m | 2 = 0.5m | 3 = 0.1m) +0x1A = Macro (0 = off | 1 = on) +0x1B = Zoom (0 = off | 1 = on) +0x1C - 0x1D = Rapport avec la carte mémoire : surement sa présence + sa taille ?? +0x1E = capture (0 = single | 1 = sequence 9) +0x1F = Date display (0 = off | 1 = on) +0x20 = Date display in play mode (0 = on | 1 = off) +0x21 = Date option (0 = M/D/Y | 1 = D/M/Y | 2 =Y/M/D) +0x22 - 0x25 = date and the time +0x25 - 0xFF = seems to be unused - The "00 84" could be a pointer to the next image number (the image - queried here is 0x83/131). +Image's Information buffer : +0x00 - 0x01 = ??? +0x02 - 0x03 = maybe the number of the next image ? +0x04 - 0x07 = seems to be Thumbnail size (in bytes) +0x08 - 0x0B = Image size (in bytes) +0x0E - 0x0F = Image number associated to this image info +0x0B - 0x10 = ??? +0x11 = Image protected (0x0 = no protection | 0x1 = Image protected) +0x12 - 0xFF = seels to be unused -4. Download Image - - Command: ESC G F (1B 47 46 3x 3x 3x 3x) - while (!finished) { - Reply: 1 byte, 01 for ok, EOT (04) for end of data. - Reply: 512 byte of image data. - Reply: 1 byte of checksum. - Command: ACK (06) - } - Loads up to len/512 blocks or up to EOT. + + +Escape codes of the windows driver: + +Ping: + Writes 2 byte: 1B 58 ESC X + Expects: 1 byte NACK/ACK + +Getcaminfo: + Writes 2 byte: 1B 53 ESC S + Expects: 1 byte NACK or 256 byte data. + The 256 byte data must start with bytes: 03 03. + +cmd_C: UNSUPPORTED ! + Writes 6 byte: 1B 43 ESC C x x y y + + Gets 2 numbers as argument. + Expects: 1 byte, NACK/ACK + +cmd_H: UNSUPPORTED ! + Writes 4 byte: 1B 48 ESC H x x + + The numbers are from a 8bit value passed to the command. + + Expects: 1 byte, NACK/ACK. + +SetSpeed: + Writes 3 byte: 1B 42 ESC B x + + Speeds are mapped to this (ascii) number: + 0 - 9600 + 1 - 19200 + 2 - 38400 + 3 - 57600 + 4 - 115200 + + Expects: 1 byte: NACK/ACK. + +ImageInfo 1: + Writes 6 byte: 1B 49 ESC I xxxx + + Expects: 1 byte NACK or 256 byte data. + The 256 byte data must start with 03 03. + +ImageInfo 2: + Writes 7 byte: 1B 49 46 ESC I F xxxx + + Expects: 1 byte NACK or 256 byte data. + + The data is the same as in ImageInfo 1. + + Unclear what the difference between the 2 commands is. + +cmd_P 1: UNSUPPOTED ! + Writes 10 byte: 1B 50 + ESC P xxxxyyyy + + Expects: 1 byte NACK or 1024 byte data (?). + +cmd_P 2: UNSUPPORTED ! + Writes 11 byte: 1B 50 46 + ESC P F xxxxyyyy + Expects: 1 byte NACK or 1024 byte data (?). + + +cmd_V 1: UNSUPPORTED ! + Writes 6 byte: 1B 56 ESC V xxxx + Expects: 1 byte NACK/ACK. + +cmd_V 2: UNSUPPORTEd ! + Writes 7 byte: 1B 56 46 ESC V F xxxx + Expects: 1 byte NACK/ACK. + +Erase 1 (not used in win driver): + Writes 6 byte: 1B 45 ESC E xxxx + Expects: 1 byte NACK/ACK + +Erase 2 (used): + Writes 7 byte: 1B 45 46 ESC E F xxxx + Expects: 1 byte NACK/ACK + + +cmd_K 1: UNSUPPORTED ! + Writes 6 byte: 1B 4B ESC K xxxx + Expects: 1 byte NACK/ACK. + +cmd_K 2: UNSUPPORTED ! + Writes 7 byte: 1B 4B 46 ESC K xxxx + Expects: 1 byte NACK/ACK. + +Capture: + Writes 3 byte: 1B 52 ESC R x + Expects: 1 byte NACK/ACK. + + can be '1' or '0'. + +Set Time (?): do nothing ? + Writes 11 byte: 1B 57 44 <8*nr> ESC W D xxxxxxxx + Expects: 1 byte NACK/ACK. + + The number is the current time in seconds sinc 1980 I guess. + +Get Thumbnail 1: + Writes: 6 byte 1B 54 <4*nr> ESC T xxxx + Expects: ... see code + +Get Thumbnail 2: + Writes: 7 byte 1B 54 46 <4*nr> ESC TF xxxx + Expects: ... see code + +Get Image 1: + Writes: 6 byte 1B 47 <4*nr> ESC G xxxx + Expects: ... see code + +Get Image 2: + Writes: 7 byte 1B 47 46 <4*nr> ESC GF xxxx + Expects: ... see code + +Upload: + Writes: 2 byte 1B 55 ESC U + Expects: ... see code +